如何用下划线对一系列承诺进行分组?
How to group by a range of promises with underscore?
我可以成功地从 redis 收集指标,但我还想通过设备 ID 收集它。最简单的方法是什么?
在这里,我使用下划线和蓝鸟。
想要的对象:
[
{
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 的值的承诺,这使得在第二步中处理它们变得更加困难。
那么这个怎么样:
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();
通过这种方式,您可以获得包含 deviceId
、metric
和来自 Redis 的关联 data
的值的承诺数组。
在 Promise.all(signals)
之后可以将其分组 data/massaging 成形状。
更易读且更易于重用:
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(...)
假定RedisAPI使用Bluebird promises,即var Promise = require('Bluebird');
应该在导入Redis之前完成。
普通的 Promise API 不支持 .map()
,如果 Redis 有自己的 Promise 实现,您必须手动执行此操作。
我可以成功地从 redis 收集指标,但我还想通过设备 ID 收集它。最简单的方法是什么?
在这里,我使用下划线和蓝鸟。
想要的对象:
[
{
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 的值的承诺,这使得在第二步中处理它们变得更加困难。
那么这个怎么样:
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();
通过这种方式,您可以获得包含 deviceId
、metric
和来自 Redis 的关联 data
的值的承诺数组。
在 Promise.all(signals)
之后可以将其分组 data/massaging 成形状。
更易读且更易于重用:
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(...)
假定RedisAPI使用Bluebird promises,即var Promise = require('Bluebird');
应该在导入Redis之前完成。
普通的 Promise API 不支持 .map()
,如果 Redis 有自己的 Promise 实现,您必须手动执行此操作。