8

如何在 Mongoose 中管理批量保存?我看到它可能还不可能:

有人提到使用一些流控制库,例如q,但我也注意到猫鼬中有承诺,可以使用吗?我可以在 jQuery Deferred/Promises 中做喜欢的事吗

$.when(obj1.save(), obj2.save(), obj3.save()).then ->
    # do something? 
4

8 回答 8

9

是的,你可以通过 Promise 做到这一点。如果您使用的是Q Promise 库,您可以重写 @matz3 的代码,例如:

var tasks = [];

for (var i=0; i < docs.length; i++) {
  tasks.push(docs[i].save());
}

Q.all(tasks)
  .then(function(results) {
    console.log(results);
  }, function (err) {
    console.log(err);
  });

我们在循环中一次启动所有操作,但我们不等待其中任何一个完成,因此它们并行运行。我们向一个数组添加一个 Promise(其作用类似于结果的占位符)。然后我们等待 promise 数组中的所有 promise 完成。

大多数好的Promises/A+兼容库都有一些等价于Q.all

于 2013-07-02T08:43:39.387 回答
6

mongoose 现在允许您选择哪个 Promise 实现。

这里我使用的是 node.js 默认系统 Promise (ES6) 烘焙到 nodejs

var mongoose = require('mongoose');
    mongoose.Promise = global.Promise; // use system implementation

Promise.all(obj1.save(), obj2.save(), obj3.save())
.then(function(resultSaves) {

    console.log('parallel promise save result :');
    console.log(resultSaves);
    mongoose.disconnect();

}).catch(function(err) {

    console.log('ERROR on promise save :');
    console.log(err);
    mongoose.disconnect();
});

节点 --version v4.1.1

猫鼬@4.1.8

于 2015-09-25T03:05:48.150 回答
5

由于mongoose现在支持你可以使用的承诺Promise.all().then(),所以当所有承诺都解决后它会返回。

Promise.all([
  obj1.save(),
  obj2.save(),
  obj3.save()
])
.then(console.log)
.catch(console.error)

事实上,如果你总是调用这个save()方法,你可以在Array.map()这里使用:

Promise.all([ obj1, obj2, obj3 ].map( obj => obj.save() )

Aaand 还使用 es6 语法来解构生成的数组:

Promise.all(
  [ obj1, obj2, obj3 ]
  .map( obj => obj.save() )
)
.then( ([ savedObj1, savedObj2, savedObj3 ]) => {
   // do something with your saved objects...
})
于 2017-04-19T15:27:43.523 回答
3

试试异步模块的并行功能。

var functions = [];

for (var i=0; i < docs.length; i++) {
    functions.push((function(doc) {
        return function(callback) {
            doc.save(callback);
        };
    })(docs[i]));
}

async.parallel(functions, function(err, results) {
    console.log(err);
    console.log(results);
});
于 2012-08-20T06:29:35.057 回答
2

要并行保存多个 mongoose 文档,您可以执行以下简单操作(假设您有一个名为docs要保存的文档的数组):

var count = docs.length;
docs.forEach(function(doc) {
    doc.save(function(err, result) {
        if (--count === 0) {
            // All done; call containing function's callback
            return callback();
        }
    });
});
于 2012-08-15T15:03:29.583 回答
1

一个关于如何使用异步并行的精炼示例是:

  async.parallel([obj1.save, obj2.save, obj3.save], callback);

由于 Mongoose 中的约定与 async (err, callback) 中的约定相同,因此您无需将它们包装在您自己的回调中,只需将您的保存调用添加到一个数组中,当一切完成时您将收到一个回调。

于 2013-04-17T19:00:37.453 回答
-1

怎么样async.queue
一个简单的例子:

var queue = async.queue(function(obj, callback) {
  return obj.save(callback);
});

for (var i in objs) {
  var obj = objs[i];
  // Some changes on object obj
  queue.push(obj);
}

如果队列清空后需要回调:

var emptyQueue = true;
var queue = async.queue(function(obj, callback) {
  return obj.save(callback);
});
queue.drain = function() {
  // Every callbacks are finished
  // bigCallback();
};

for (var i in objs) {
  var obj = objs[i];
  // Some changes on object obj
  queue.push(obj);
  emptyQueue = false;
}
if (emptyQueue) {
  // Call manually queue drain in case of the queue is empty
  //  and we need to call bigCallback() for example
  return queue.drain();
}
于 2014-02-22T00:49:18.347 回答
-1

@ForbesLindesay 当您可以使用承诺的猫鼬实现并创建自己的 All 时,为什么要加载外部库?

创建一个模块来增强 mongoose 的承诺。

var Promise = require("mongoose").Promise;

Promise.all = function(promises) {
  var mainPromise = new Promise();
  if (promises.lenght == 0) {
    mainPromise.resolve(null, promises);
  }

  var pending = 0;
  promises.forEach(function(p, i) {
    pending++;
    p.then(function(val) {
      promises[i] = val;
      if (--pending === 0) {
        mainPromise.resolve(null, promises);
      }
    }, function(err) {
      mainPromise.reject(err);
    });
  });

  return mainPromise;
}

module.exports = Promise;

然后将它与猫鼬一起使用:

require('./promise')

...

var tasks = [];

for (var i=0; i < docs.length; i++) {
  tasks.push(docs[i].save());
}

mongoose.Promise.all(tasks)
  .then(function(results) {
    console.log(results);
  }, function (err) {
    console.log(err);
  });
于 2015-06-16T19:27:52.070 回答