nodejs等待循环完成所有MongoDB调用

时间:2015-11-12 04:10:23

标签: javascript node.js mongodb asynchronous promise

我正逐行从CSV文件中读取数据流,并在每一行上调用findOne MongoDB调用,在运行下一个函数之前,我怎么能等到每行的所有mongo调用都完成? / p>

我见过Promise可以做到吗?但我觉得Promises极难理解。我发现的所有例子都没有涵盖我正在尝试的内容。 :/

var validProducts = [];

fs.createReadStream(req.file.path)
  .pipe(csvStream)
  .on('error', function (err) {
    console.error(err);
  })
  // loop through all rows
  .on('data', function (data) {
    if (data.size === 'a3') {
      ProductModel.findOne({ sku: data.sku }, function (err, product) {
        if (product !== null) {
          product.size = data.size;
          product.save();
          validProducts.push(product);
        }
      });
    }
  });

// on finish make call to other function
socket.emit({ 'status': 'complete' });
otherFunction(validProducts);

on('finish')on('end')只会在数据流的末尾调用,而不是在Monogo调用之后调用。

如果我可以使用承诺,有人可以解释一下吗?

2 个答案:

答案 0 :(得分:4)

你可以使用Q API,让你做出承诺。有一个有趣的功能,允许您等待一系列的承诺得到解决。以下是使用Q.all解决问题的示例:

var validProducts = [];
var promises = [];

function handleData(data) {
    if (data.size === 'a3') {

        var deferred = Q.defer();

        ProductModel.findOne({ sku: data.sku }, function (err, product) {
            if (err) {
                deferred.reject(new Error(err));
            }

            if (product) {
                product.size = data.size;
                product.save();
                deferred.resolve(product);
                validProducts.push(product);
            }

        });

        promises.push(deferred.promise);

    }
}

function handleEnd() {
    Q.all(promises).done(function (values) {
        socket.emit({ 'status': 'complete' });
        otherFunction(validProducts);
    });
}

fs.createReadStream(req.file.path)
  .on('data', handleData)
  .on('end', handleEnd);

答案 1 :(得分:3)

使用pause / resume

i = (Max-1 + i)%Max