Node.js 在节点中的异步调用后执行某些操作

Node.js 在节点中的异步调用后执行某些操作,node.js,asynchronous,Node.js,Asynchronous,假设我有四个不同的异步操作需要运行,它们都可以独立运行。但是还有一个剩余的函数需要使用这些异步调用收集的所有数据,因此只有在所有调用完成后才能执行 一种简单的方法是让异步调用一个接一个地互相调用,然后最后调用final函数,如下所示: myObj.async1(function () { myObj.async2(function () { myObj.async3(function () { myObj.async4(function () { ...

假设我有四个不同的异步操作需要运行,它们都可以独立运行。但是还有一个剩余的函数需要使用这些异步调用收集的所有数据,因此只有在所有调用完成后才能执行

一种简单的方法是让异步调用一个接一个地互相调用,然后最后调用final函数,如下所示:

myObj.async1(function () {
  myObj.async2(function () {
    myObj.async3(function () {
      myObj.async4(function () {
         ...
         finalFunction();
但这是一种糟糕的方法,因为节点是围绕异步功能构建的,这是有原因的。因此,让我们假设我们想做:

myObj.async1(async1Callback);
myObj.async2(async2Callback);
myObj.async3(async3Callback);
myObj.async4(async4Callback);

if( //Some logic here to determine when all four functions have completed
  finalFunction();
确定这种逻辑的最佳方法是什么?我考虑过让每个函数设置一个布尔变量来指示它是否已经完成,然后让一个基于时间的发射器不断检查所有四个变量是否都设置为true,如果设置为true,则调用finalFunction,但如果所有这些变量都存在,则可能会造成混乱

你有什么想法吗?

我会利用图书馆来做这件事,例如

async.parallel([
  myObj.async1,
  myObj.async2,
  myObj.async3,
  myObj.async4
], function(err) {
  if (err) throw err;

  // Run final function now that all prerequisites are finished
  finalFunction();
});
这假设每个
myObj.async*
函数
都将回调
函数
作为其唯一参数,并且回调的第一个参数是
err
参数。有关更多信息,请参阅。

我将利用此库,例如

async.parallel([
  myObj.async1,
  myObj.async2,
  myObj.async3,
  myObj.async4
], function(err) {
  if (err) throw err;

  // Run final function now that all prerequisites are finished
  finalFunction();
});

这假设每个
myObj.async*
函数
都将回调
函数
作为其唯一参数,并且回调的第一个参数是
err
参数。有关更多信息,请参阅@jabclab推荐的。

,看看它为您管理了许多复杂性。然而,如果你想自己做这样的事情,这里有几个选择

从一个myObj开始,它看起来像:

var myObj = {
    async1: function async1(cb) { setTimeout(function() {
        console.log('async1');
        cb(null, {name: 'async1'});
    }, 1000)},
    async2: function async2(cb) { setTimeout(function() {
        console.log('async2');
        cb(null, {name: 'async2'});
    }, 500)},
    async3: function async3(cb) { setTimeout(function() {
        console.log('async3');
        cb(null, {name: 'async3'});
    }, 1001)},
    async4: function async4(cb) { setTimeout(function() {
        console.log('async4');
        cb(null, {name: 'async4'});
    }, 200)}
}
此版本硬编码为调用四个特定函数,并在结果完成时回调。结果按完成顺序以数组形式传回。每个结果对象都包含函数名以及任何错误或成功结果

function doFourSpecificThings(callback) {
    var results = [];

    var storeResults = function(fnName, err, resp) {
        results.push( { fnName: fnName, err: err, resp: resp } );

        if(results.length === 4 && callback) {
            callback(results);
        }
    }

    // Bind the callback to myObj and pass the name of the called function 
    // as the first argument
    myObj.async1(storeResults.bind(myObj, 'async1'));
    myObj.async2(storeResults.bind(myObj, 'async2'));
    myObj.async3(storeResults.bind(myObj, 'async3'));
    myObj.async4(storeResults.bind(myObj, 'async4'));
}

doFourSpecificThings(function(results) {
    console.log(results);
});
输出:

async4
async2
async1
async3

Results:
[ { fnName: 'async4', err: null, resp: { name: 'async4' } },
  { fnName: 'async2', err: null, resp: { name: 'async2' } },
  { fnName: 'async1', err: null, resp: { name: 'async1' } },
  { fnName: 'async3', err: null, resp: { name: 'async3' } } ]
async4
async2
async1
async3

Results:
[ { err: null, resp: { name: 'async1' } },
  { err: null, resp: { name: 'async2' } },
  { err: null, resp: { name: 'async3' } },
  { err: null, resp: { name: 'async4' } } ]
这个版本有点灵活。任务作为数组传入,结果以相同的顺序存储在结果数组中:

function doABunchOfStuff(tasks, callback) {
    var results = [];
    var expected = tasks.length;

    var storeResults = function(idx, err, resp) {
        results[idx] = { err: err, resp: resp };

        --expected;
        if((expected === 0) && callback) {
            callback(results);
        }
    }

    // Using bind here to pass the current index to the storeResults()
    // callback as the first parameter
    for(var i = 0; i < tasks.length; ++i) {
        tasks[i](storeResults.bind(tasks[i], i));
    }
}

doABunchOfStuff([
    myObj.async1.bind(myObj),
    myObj.async2.bind(myObj),
    myObj.async3.bind(myObj),
    myObj.async4.bind(myObj)], 
    function(results) {
        console.log('\nResults:');
        console.log(results);
    });

正如@jabclab所推荐的那样,看看它为您管理了很多复杂性。然而,如果你想自己做这样的事情,这里有几个选择

从一个myObj开始,它看起来像:

var myObj = {
    async1: function async1(cb) { setTimeout(function() {
        console.log('async1');
        cb(null, {name: 'async1'});
    }, 1000)},
    async2: function async2(cb) { setTimeout(function() {
        console.log('async2');
        cb(null, {name: 'async2'});
    }, 500)},
    async3: function async3(cb) { setTimeout(function() {
        console.log('async3');
        cb(null, {name: 'async3'});
    }, 1001)},
    async4: function async4(cb) { setTimeout(function() {
        console.log('async4');
        cb(null, {name: 'async4'});
    }, 200)}
}
此版本硬编码为调用四个特定函数,并在结果完成时回调。结果按完成顺序以数组形式传回。每个结果对象都包含函数名以及任何错误或成功结果

function doFourSpecificThings(callback) {
    var results = [];

    var storeResults = function(fnName, err, resp) {
        results.push( { fnName: fnName, err: err, resp: resp } );

        if(results.length === 4 && callback) {
            callback(results);
        }
    }

    // Bind the callback to myObj and pass the name of the called function 
    // as the first argument
    myObj.async1(storeResults.bind(myObj, 'async1'));
    myObj.async2(storeResults.bind(myObj, 'async2'));
    myObj.async3(storeResults.bind(myObj, 'async3'));
    myObj.async4(storeResults.bind(myObj, 'async4'));
}

doFourSpecificThings(function(results) {
    console.log(results);
});
输出:

async4
async2
async1
async3

Results:
[ { fnName: 'async4', err: null, resp: { name: 'async4' } },
  { fnName: 'async2', err: null, resp: { name: 'async2' } },
  { fnName: 'async1', err: null, resp: { name: 'async1' } },
  { fnName: 'async3', err: null, resp: { name: 'async3' } } ]
async4
async2
async1
async3

Results:
[ { err: null, resp: { name: 'async1' } },
  { err: null, resp: { name: 'async2' } },
  { err: null, resp: { name: 'async3' } },
  { err: null, resp: { name: 'async4' } } ]
这个版本有点灵活。任务作为数组传入,结果以相同的顺序存储在结果数组中:

function doABunchOfStuff(tasks, callback) {
    var results = [];
    var expected = tasks.length;

    var storeResults = function(idx, err, resp) {
        results[idx] = { err: err, resp: resp };

        --expected;
        if((expected === 0) && callback) {
            callback(results);
        }
    }

    // Using bind here to pass the current index to the storeResults()
    // callback as the first parameter
    for(var i = 0; i < tasks.length; ++i) {
        tasks[i](storeResults.bind(tasks[i], i));
    }
}

doABunchOfStuff([
    myObj.async1.bind(myObj),
    myObj.async2.bind(myObj),
    myObj.async3.bind(myObj),
    myObj.async4.bind(myObj)], 
    function(results) {
        console.log('\nResults:');
        console.log(results);
    });

谢谢你的评论。非常有帮助。谢谢你的评论。非常有用。