1

我有一个问题,但我不知道如何解决这个问题。

我正在使用环回,但我想我迟早会在 mongodb 中遇到同样的问题。让我解释一下我在做什么:

  • 我从另一个 REST 服务获取条目,然后为我的 API 响应准备条目(条目尚未准备好,因为它们没有来自我的数据库的 id)
  • 在我发送响应之前,我想检查数据库中是否存在条目,如果不存在:
    • 如果有,则创建它(由 source_id 确定):
    • 使用它并将其更新到新版本
  • 发送带有条目的响应(条目现在具有分配给它们的数据库 ID)

这似乎没问题,并且易于实施,但据我所知还不是。我将尝试在代码中进一步解释:

//This will not work since there are many async call, and fixedResults will be empty at the end
var fixedResults = [];
//results is array of entries
results.forEach(function(item) {
    Entry.findOne({where: {source_id: item.source_id}}, functioN(err, res) {
        //Did we find it in database?
        if(res === null) { 
            //Create object, another async call here
            fixedResults.push(newObj);
        } else {
            //Update object, another async call here
            fixedResults.push(updatedObj);
        }
    });
});
callback(null, fixedResults);

注意:我遗漏了一些代码,但如果你通读它,我认为它是不言自明的。

所以我想遍历所有对象,在数据库中创建或更新它们,然后当所有对象都被更新/创建时,使用它们。我该怎么做?

4

4 回答 4

1

你可以使用承诺。它们是在其他条件完成后将调用的回调。这是一个将 Promise 链接在一起的示例https://coderwall.com/p/ijy61g

q库是一个很好的库 - https://github.com/kriskowal/q

这个问题如何使用 q.js promises to work with multiple asynchronous operations提供了一个很好的代码示例,说明如何构建这些操作。

于 2014-07-16T19:12:58.123 回答
1

这种模式通常称为“异步映射”

var fixedResults = []; var outstanding = 0; //results is array of entries results.forEach(function(item, i) { Entry.findOne({where: {source_id: item.source_id}}, functioN(err, res) { outstanding++; //Did we find it in database? if(res === null) { //Create object, another async call here DoCreateObject(function (err, result) { if (err) callback(err); fixedResults[i] = result; if (--outstanding === 0) callback (null, fixedResults); }); } else { //Update object, another async call here DoOtherCall(function (err, result) { if(err) callback(err); fixedResults[i] = result; if (--outstanding === 0) callback (null, fixedResults); }); } }); }); callback(null, fixedResults);

于 2014-07-16T19:17:40.150 回答
0

您可以为此使用async.map。对于数组中的每个元素,运行数组迭代器函数对每个元素执行您想要执行的操作,然后使用结果运行回调(而不是 fixedResults.push),当所有操作完成后触发映射回调。然后将并行运行每个迭代广告数据库调用。

于 2014-07-16T19:18:22.967 回答
0

Mongo 有一个叫做 upsert 的函数。

http://docs.mongodb.org/manual/reference/method/db.collection.update/

它完全符合您的要求,无需检查。您可以触发所有三个请求 asnc 并验证结果是否为真。无需额外处理。

于 2014-07-16T19:23:04.387 回答