nodejs async执行串行回调

时间:2013-12-03 23:11:04

标签: node.js asynchronous

我的情况如下:

function smth(data) {
   // save data to db.
   Object.findOne({ _id: ceva['id']}, function(obj) {
     obj.save();
   });

}

从各种异步调用中调用此函数。存在竞争条件,其中第二个findOne调用在先前的save()运行之前运行。

有办法解决这个问题吗?也许使用异步库来串行运行?

2 个答案:

答案 0 :(得分:1)

//make this follow async conventions with callback argument last
function smth(data, callback) {
   //pseudocode database API here
   db.save(data, function (error) {
     if (error) {
       callback(error);
       return;
     }
     Object.findOne({ _id: ceva['id']}, function(obj) {
       obj.save(callback);
     });
   });
}

这是基本的回调方法。如果您想稍微清理一下,可以使用async.js,或者学习callbackhell.com以了解更多避免嵌套函数的方法。

答案 1 :(得分:1)

您可以使用async控制流之一来确保smth()的每次迭代按顺序发生。

如果您不赞成使用流控制库,则可以轻松实现每个事件的系列执行。请考虑以下代码段:

function smth(data, cb) {
  // save data to db.
  findOne({
    id: data.id
  }, function (err, obj) {
    if (!err && obj) {
      savedb(obj, cb);
    } else {
      cb(err);
    }
  });
}

function findOne(filter, cb) {
  // simulate find
  setTimeout(function () {
    cb(null, {
      id: filter.id,
      name: 'test',
      role: 'test'
    });
  }, 500);
}

function savedb(obj, cb) {
  //simulate db save
  setTimeout(function () {
    cb(null, obj);
  }, 500);
}

// iterations count
var count = parseInt(process.argv[2], 10) || 3;

(function iterate(i) {
  console.log(i);
  if (i === count) {
    // iterations complete
    process.exit(1);
  }

  var data = {
    id: 123 + i
  };

  smth(data, function (err, res) {
    console.log(err || res);
    iterate(++i);
  });
})(0);