Return q 在所有操作完成时解决

Return q resolve when all operations complete

我有一个函数,我只想在 foreach 完成时解决。我使用 q 和 mongoose,这是大写的东西所指的,基本上我想先创建一组项目,然后运行 foreach完成后的一个函数。

function createItems() {

  var deferred = Q.defer();

  var itemsArray = [{ 'name' : 'spade' }, { 'name' : 'bucket' } , { 'name' : 'sand'}];

  itemsArray.forEach(function(itemObj) {
    var item = new Item(itemObj); // forces it to use a schema (dont worry)
    Item.findOneAndUpdate({
      url: item.short_name
    }, item, {
      upsert: true
    }, function(err) {
      if (!err) {
        console.log(item.name + ' created.');
        deferred.resolve();
      } else {
        deferred.reject(new Error(err));
      }
    });
  });


  return deferred.promise;
}

createItems()
    .then(function() {
      console.log('All items done.');
    });

所以我希望在控制台上看到类似的东西;

已创建黑桃项目 已创建存储桶项目 沙项目创建 所有项目完成。

顺便说一句:您的数组存在语法问题,它包含一个对象,多次尝试写入 name。我假设你打算有一个对象数组,每个对象都有一个 name.

基本上,你的方法失败了,因为你在一开始就兑现了你的承诺。您需要一个代表多个异步调用完成的承诺。做到这一点的标准方法是将 承诺数组 传递到库函数中,例如 Q.all / Bluebird.all / Promise.allall 函数接受一组承诺,returns 接受一组结果的承诺。它在所有承诺都解决时解决,或者在任何一个承诺拒绝时拒绝。

function createItems() {

  var promisesForUpdatedDocs = [];

  var itemsArray = [
    { name: 'spade'},
    { name: 'bucket'},
    { name: 'sand'}
  ];

  itemsArray.forEach(function(itemObj) {
    var item = new Item(itemObj);
    var updatedDocPromise = Item.findOneAndUpdate({
      url: item.short_name
    }, item, {
      upsert: true
    }).exec(); // returns an mPromise
    promisesForUpdatedDocs.push(Q(updatedDocPromise)); // using Q to turn the mPromise to a Q promise, and adding it to an array
  });

  return Q.all(promisesForUpdatedDocs); // creates a promise for array of results (from array of promises)
}

createItems()
  .then(function(items) {
    console.log('All items done:', items);
  }).catch(console.log); // never forget to handle errors! Always `return` or `catch` a promise chain.