您如何将函数调用推送到数组而不在 Node JS 中调用它们以使用 Q?

How do you push function calls onto an array without calling them in Node JS for using Q?

我想创建一个函数数组来动态调用,稍后将在 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
        });
    });
});

但是直到运行时我才知道数据的长度

我建议为此使用 Promise.mapSeries 或异步库,因为它很容易捕获错误。如果回调中有数据库调用,使用 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
  });

 async.eachOfSeries(data, function(dataInstance, key, next) {
    functionCall(dataInstance, function(err , result){
        if(err)
          {
            console.log(err);
            next(err);
          }
          else
            next();
    });
  }, function() {
        //iteration completed
  });

如果我没理解错的话,你想调用 functionCall 获取一组项目,并在 functionCall 编辑的所有承诺 return 完成后让 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 
});

Note: the above can be simplified to

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 
});

the edited question suggests you can perform the actions in series also - in series it would be

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 并且需要 return 一个承诺 如果 你需要等待它完成才能处理下一个数据项。如果您不需要等待 mongo 日志记录完成,那么该函数就不需要 return 承诺