我希望创建一个动态调用的函数数组,稍后将在Q.all([])promise调用中使用。
例如;
//data is previously generated
var promiseArray = [];
for (var i = 0; i < data.length; i++){
promiseArray.push(functionCall(data[i]))
}
Q.all(promiseArray).then(function(){
//Do something
})
在Q.all语句之前,如何在不调用函数的情况下推送到数组?我不想在for循环中调用它,因为它不会捕获任何错误,我无法进一步处理响应。
编辑:
所以为了澄清我的问题(因为我认为我没有像我应该的那样清晰),这里有一个静态数据长度为3的解决方案;
//data is previously generated
var data = [12432432,4324322392,433324323];
//Each function call can happen in parallel or series as its an external POST to an API
//I'm not bothered about speed for this application (as its low throughput) and can wait a few seconds for each
// response
//FunctionCall returns a promise
functionCall(data[0]).then(function(){
//Log success / failure to mongo
});
functionCall(data[1]).then(function(){
//Log success / failure to mongo
});
functionCall(data[2]).then(function(){
//Log success / failure to mongo
});
//OR
functionCall(data[0]).then(function(){
//Log success/failure to mongo
functionCall(data[1]).then(function(){
//Log success/failure to mongo
functionCall(data[2]).then(function(){
//Log success/failure to mongo
});
});
});
但是直到运行时我才知道数据的长度
答案 0 :(得分:1)
如果我理解正确,您希望为functionCall
调用一系列项目,并且functionCall
返回的所有承诺已完成后,Q.all会解析如果他们解决或拒绝 - 如果你不关心结果(因为你的代码中似乎没有),只需处理你推动的承诺中的拒绝 - 即
var promiseArray = [];
for (var i = 0; i < data.length; i++) {
promiseArray.push(functionCall(data[i]).then(function(result) {
// log success
return logToMongoFunction(result);
}, function(error) {
// log failure
return logToMongoFunction(error);
}).catch(function(error) {
// catch and ignore any error thrown in either logToMongoFunction above
return;
}));
}
Q.all(promiseArray).then(function () {
//Do something
});
注意:以上内容可以简化为
Q.all(data.map(function (item) {
return functionCall(item).then(function(result) {
// log success
return logToMongoFunction(result);
}, function(error) {
// log failure
return logToMongoFunction(error);
}).catch(function(error) {
// catch and ignore any error thrown in either logToMongoFunction above
return;
});
})).then(function() {
//Do something
});
编辑过的问题建议您也可以按顺序执行这些操作 - 这将是
data.reduce(function(promise, item) {
return promise.then(function() {
return functionCall(item).then(function(result) {
// log success
return logToMongoFunction(result);
}, function(error) {
// log failure
return logToMongoFunction(error);
}).catch(function(error) {
// catch and ignore any error thrown in either logToMongoFunction above
return;
});
});
}, Promise.resolve()).then(function() {
// all done
});
而不是Promise.resolve()
您可以使用Q
所拥有的任何内容作为创建已解决承诺的等价物
logToMongoFunction
会记录到mongo并需要返回一个承诺如果你需要等待它完成才能处理下一个数据项。如果您不需要等待mongo日志记录完成,那么该函数不需要返回一个promise
答案 1 :(得分:0)
我建议使用Promise.mapSeries或async库,因为它很容易捕获错误。如果在回调中有数据库调用,那么使用for循环循环的另一件事似乎不是好方法,因为这可能会刷新对数据库的调用,而node.js可能会出现内存问题,或者node.js无法接受任何其他请求,因为它将忙于在for循环中娱乐请求。所以它总是很好地连续运行循环或一次限制并行执行的数量。
请参阅下面的示例
This will run Array serially one at a time when 1st one completes execution next will be called
async.eachOfSeries(data, function(dataInstance, key, next) {
functionCall(dataInstance).then(function(){
next();
}).catch(funtion(err){
next(err);
})
}, function() {
//iteration completed
});
OR
async.eachOfSeries(data, function(dataInstance, key, next) {
functionCall(dataInstance, function(err , result){
if(err)
{
console.log(err);
next(err);
}
else
next();
});
}, function() {
//iteration completed
});