如何在路由器中延迟响应?

How to deferred response in router?

我想使用 sequelize orm 从多个表中收集数据。这是我的代码

var recs = [];

models.Data.findAll({
    where: {
        //exchange_id: req.params.exchangeId
        exchange_id: 7
    }
})
.then(function (data) {
    var rec = {};

    data.forEach(function (item, i) {
        console.log('\n data id is ', data[i].id);

        models.ExchangeTable.findOne({
            data_id: data[i].id
        }).then(function (exchangeTable) {
            models.Country_Money.findOne({
                id: exchangeTable.country_money_id
            }).then(function (countryMoney) {
                rec.countryMoneyId = countryMoney.id;
                rec.data = data[i];
            });
        });
    });

    recs.push(rec);
    res.json(recs);
});

输出为:

Executing (default): SELECT "id", "sell", "buy", "exchange_id", "createdAt", "up
datedAt" FROM "Data" AS "Data" WHERE "Data"."exchange_id" = 7;

 data id is  185

 data id is  186
Executing (default): SELECT "id", "data_id", "country_money_id", "createdAt", "u
pdatedAt" FROM "ExchangeTables" AS "ExchangeTable" LIMIT 1;
GET /ServiceProviders/Exchange/table/5 200 60.349 ms - 4
Executing (default): SELECT "id", "data_id", "country_money_id", "createdAt", "u
pdatedAt" FROM "ExchangeTables" AS "ExchangeTable" LIMIT 1;
Executing (default): SELECT "id", "Country_id", "Money_id" FROM "Country_Money"
AS "Country_Money" LIMIT 1;
Executing (default): SELECT "id", "Country_id", "Money_id" FROM "Country_Money"
AS "Country_Money" LIMIT 1;

我的问题是我不知道如何在循环块中使用延迟,因为给 Country_Money 模型的 where 条件提供了 Data 模型中必须提供的预期值.

请告诉我,我该如何解决这个问题?

在使用 res#json 发送响应之前,您没有等待在 forEach 中创建的承诺完成。虽然数据库查找可能需要一些时间,但它们是异步执行的,因此代码 after 的执行不会等待 forEach 完成。为了让它们 wait 我们可以换取 forEach 将迭代器中的每个 promise 映射到一个 promise:

var promises = data.map(function (item, i) {
    console.log('\n data id is ', data[i].id);

    // We must return a value here
    return models
        .ExchangeTable
        .findOne({data_id: data[i].id})
        .then(function (exchangeTable) {

            // Every promise we create must be returned so that
            // its parent waits for it to resolve before giving
            // control to the next `then`
            return models
                .Country_Money
                .findOne({id: exchangeTable.country_money_id})
                .then(function (countryMoney) {

                    // Return an object literal with the data we want
                    // instead of affecting an external store.
                    // This will be the final value for an iteration
                    // and available as a member of the array result of `Promise.all`
                    return {
                        countryMoneyId: countryMoney.id,
                        data: data[i]
                    };
                });
            });
        });

这将产生一系列可以交给 Promise#all 的承诺。最后,依赖于每个承诺的代码必须放在 Promise#all 之后的 then 内。

return Promise
    .all(promises)
    .then(function (recs) {
        // Here we receive the final result of each
        // promise returned within `data.map` as an array
        res.json(recs);
    });

使用这种方法我们不再需要维护 var recs = [];var rec = {};。查看 Array.prototype.map 的目的和行为,了解为什么会这样。