mongoose不把所有文件保存在循环中

所以我在POST api的Express应用程序中有以下代码:

var dashSchema = new mongoose.Schema({ key: 'string', status: 'string', assignee: 'string', summary: 'string' }); var dashData = mongoose.model('dashData', dashSchema); app.post('/api/data', function(req, res) { var issues = req.body.issues; for (var i=0;i<issues.length;i++) { dashData.create({key: issues[i].key, status: issues[i].fields.status.name, assignee: issues[i].fields.assignee, summary: issues[i].fields.summary}); } res.end(); }); 

每当我发布一个5个“问题”的数组时,只有前两个正在写入MongoDB。 我认为这是因为它只是在遍历循环所需的时间内写入,但我不知道如何使它写入所有的数据,然后返回响应。

有任何想法吗?

在Mongoose中, .create返回一个承诺。 安装一个像bluebird的承诺库让你访问Promise.all ,你可以这样做:

 var Promise = require('bluebird'); // could also be Q or another A+ library app.post('/api/data', function(req, res, next) { var issues = req.body.issues; // map the issues to an array of promises for created dashData docs var createdPromises = issues.map(function(issue){ return dashData.create({key: issue.key, status: issue.fields.status.name, assignee: issue.fields.assignee, summary: issue.fields.summary}); // returns a promise }); Promise.all(createdPromises).then(function(results){ res.json(results); // only sends when all docs have been created }).then(null, next); // error handler - pass to `next` }); 

最简单的方法是在达到最后一次迭代时结束响应:

  for (var i=0;i<issues.length;i++) { dashData.create({key: issues[i].key, status: issues[i].fields.status.name, assignee: issues[i].fields.assignee, summary: issues[i].fields.summary}); if(i === issues.length - 1) return res.end(); } 

或者,您可以使用asynchronous模块来获得更多function,尤其是在需要等待所有查询完成的情况下。

更新

正如Gabriel正确指出的那样,上面的代码并不能确保查询在发送响应之前完成执行。 我想我已经提到你应该使用asynchronous, especially if you need to wait for all the queries to complete 。 无论如何,如果你希望没有asynchronous或承诺的开销,你可以做一些事情:

  var ctr = 0; issues.forEach(function(issue){ dashData.create({key: issue.key, status: issue.fields.status.name, assignee: issue.fields.assignee, summary: issue.fields.summary}, function(err, doc){ if (err) { return errorHandler(err); } ctr++; if (ctr === issues.length) return res.end(); }); });