javascript - 如何用下划线对一系列 promise 进行分组?

标签 javascript promise underscore.js bluebird

我可以成功从 Redis 收集指标,但我还想通过设备 ID 收集它。最简单的方法是什么?

在这里,我使用下划线和 bluebird。

所需对象:

[
  { 
    deviceId    : 'foo',

    stats: [
      {
        date        : '20160215',
        temperature : 32.3,
        uptime      : 10.0,
        frequency   : 0.2
      },
      {
        date        : '20160216',
        temperature : 12.3,
        uptime      : 15.0,
        frequency   : 0.3
      }
      // ,...
    ]
  },

  { 
    deviceId    : 'bar',

    stats: [
      {
        date        : '20160215',
        temperature : 42.3,
        uptime      : 0.3,
        frequency   : 0.5
      },
      {
        date        : '20160216',
        temperature : 32.3,
        uptime      : 1.2,
        frequency   : 0.5
      }
      // ,...
    ]
  }
]

数据以有序集的形式存储在redis中:

// metric:device:device-id:daily

temperature:device:standart-faf4-4279-a040-0e729e53f5c1:daily
uptime:device:standart-faf4-4279-a040-0e729e53f5c1:daily
frequency:device:standart-faf4-4279-a040-0e729e53f5c1:daily

我的代码:

  var metrics = [ 'temperature', 'uptime', 'frequency' ];

  var signals = _
    .chain(statsOfToday)
    .pluck('deviceId')
    .map(function(deviceId) {
      return _.map(metrics, function(metric) {
        return redis.zrangebyscoreAsync(
          metric +":device:"+ deviceId +":daily",
          20160215, 20160216
        );
      })
    })
    .flatten()
    .value();

  // in here deviceId is lost
  return Promise.all(signals)
    .then(function(results) {
      return _
        .chain(results)
        .flatten()
        .map(function(x) {
          // data in redis stored as: metric-timestamp
          return x.split("-")[0];
        })
        .value();
    });

最佳答案

据我所知,您的第一个语句会产生一系列不包含它们引用的 deviceId 的值的 promise ,这使得第二步中处理它们变得更加困难。

那么这个怎么样:

var signals = _
  .chain(statsOfToday)
  .pluck('deviceId')
  .map(function(deviceId) {
    return _.map(metrics, function(metric) {
      return redis.zrangebyscoreAsync(
        metric +":device:"+ deviceId +":daily", 20160215, 20160216
      ).then(function (data) {
        return data.map(function (item) {
            return {
              deviceId: deviceId,
              metric: metric,
              data: item.split("-")[0]
            };
        });
      });
    })
  })
  .flatten()
  .value();

通过这种方式,您可以获得包含 deviceIdmetric 以及来自 Redis 的关联data 的值的 promise 数组。

Promise.all(signals) 中可以对数据进行分组/将其调整为形状。

<小时/>

更易于阅读且更易于重用:

function getDeviceMetricAsync(deviceId, metric, min, max) {
  var key = metric + ":device:" + deviceId + ":daily";
  return redis.zrangebyscoreAsync(key, min, max).map(function (item) {
    return {
      deviceId: deviceId,
      metric: metric,
      data: item.split("-")[0]
    }
  });
}


var signals = _
  .chain(statsOfToday)
  .pluck('deviceId')
  .map(function(deviceId) {
    var retrievalFunc = _.partial(getDeviceMetricAsync, deviceId, _, 20160215, 20160216);
    return _.map(metrics, retrievalFunc);
  })
  .flatten()
  .value();

注意: redis.zrangebyscoreAsync(key, min, max).map(...) 行假定 Redis API 使用 Bluebird Promise,即 var Promise = require('Bluebird'); 应在导入 Redis 之前完成。

普通的 Promise API 不支持 .map(),如果 Redis 有自己的 Promise 实现,您必须手动执行此操作。

关于javascript - 如何用下划线对一系列 promise 进行分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35466655/

相关文章:

javascript - 批量用户创建后 Firebase 不添加文档

javascript - 在 .then() 中向函数添加参数会破坏 JS 中 Promise 的行为

javascript - document.open 如何影响历史?

javascript - 错误的ejs未定义?

Javascript:Promise.all 似乎没有解决

javascript - 如何返回数组中重复字符串的数组?

javascript - 在 console.log 中打印 Javascript 对象时的不同行为

javascript - 在 Angular 中创建具有完整独立 CSS 的页面

javascript - 通过 viewbag MVC RAZOR 传递链接并出现

javascript - 使用 setTimeout 推迟所有繁重的计算