【问题标题】:Let Node wait till all data is loaded to send response让 Node 等到所有数据都加载完毕再发送响应
【发布时间】:2016-12-11 14:57:51
【问题描述】:

情景草图

我正在使用带有 的 Node.js 制作 Web 服务器。我将在我的 Android 应用程序的 home 片段的列表中表示一些系列。如下图所示:

红色矩形是一个包含多个系列的列表。

数据

在数据库中,我创建了一个名为 lists 的集合。下面是一个文档示例:

{
    "_id" : ObjectId("486464a459f14e486012ee4a"),
    "name" : "Flemish",
    "series" : [ 61519, 64095, 11431, 16148, 63315, 68667, 8318, 61548, 62025, 36960 ]
}

series 属性在每个文档中的长度不同。

该数组中的数字代表系列中的 ID。他们来自The Movie Database (TMDb)

我会做什么

现在我将把数据库中的列表与 TMDb 中的数据合并。为此,我编写了以下代码:

const dbService = require("./../data/databaseService.js"),
      apiService = require("./../data/apiService.js"),
      express = require("express"),
      router = express.Router();

router.get("/list", (req, res, next) => {

    dbService.getLists((err, data) => {
        if (err) {
            next(err);
        }
        else {

            let seriesData = [];

            for (var listIndex = data.length - 1; listIndex--;) {

                let temp = { 
                    name: data[listIndex].name, 
                    series: [] 
                };

                for (var seriesIndex = data[listIndex].series.length - 1; seriesIndex--;) {

                    let id = data[listIndex].series[seriesIndex];

                    apiService.request(`tv/${id}?append_to_response=images,similar`, (err, data) => {
                        if (err) {
                            next(err);
                        }
                        else {
                            temp.series.push(data);
                        }
                    });
                }

                seriesData.push(temp);
            }

            res.send(seriesData);
        }
    });
});

module.exports = router;

问题

我遇到的问题是行res.send(seriesData); 被调用之前 数据被推送到数组seriesData。这发生在这条线上temp.series.push(data);。您可以在下面找到将要发送的代码:

[
    {
        "name": "British",
        "series": []
    },
    {
        "name": "American",
        "series": []
    },
    {
        "name": "Reality",
        "series": []
    },
    {
        "name": "Flemish",
        "series": []
    }
]

我知道一切都是用 Node.js 异步发生的,我对结果并不感到震惊,但现在 Node 必须等待。

问题

现在我的问题是,响应是否可以等到所有数据都从 TMDb 加载?如果是怎么做,否则为什么?

还要注意,列表中的项目必须相等。示例:“权力的游戏”系列在美国列表中,不能被推到另一个列表中。系列“Als de dijken breken”也是如此。该系列进入佛兰芒语列表,无法推入英国语。

参考

我制作了一张图片,您可以在其中再次检查代码并将每个请求和响应的结果作为 JSON 代码获取。

(点击图片查看实际尺寸)

【问题讨论】:

  • 是的,这可能是您想要的,请查看 promisesasync/await 运算符。 ponyfoo.com/articles/understanding-javascript-async-await
  • 我也建议尝试async.js
  • 我之前遇到过类似的问题,并通过类似if(seriesData.length == data[listIndex].series.length) { res.send(seriesData) } 的方式解决了这个问题。其他建议使用 Promise 或 async.js 的 cmets 几乎可以肯定是更好的想法——我开始研究 Promise,但还没有完全理解。如果有人能告诉我我的想法好不好,我很乐意学习。在我的情况下它对我有用,但感觉很hacky......

标签: express mongodb node.js express asynchronous wait


【解决方案1】:

经过搜索和测试,我终于找到了解决方案。

图书馆

对于图书馆,我使用Async.js。您可以在命令行中使用以下代码安装它:

npm install --save async

并使用 this 添加了库

const async = require("async");

我使用async.each() 方法。

这是解决问题的更简单的方法。该函数接受一个项目数组,然后迭代它们,调用一个接受项目作为参数的包装函数。当所有调用都完成后,您指定要调用的最终函数。

// 1st para in async.each() is the array of items
async.each(items,
  // 2nd param is the function that each item is passed to
  function(item, callback){
    // Call an asynchronous function, often a save() to DB
    item.someAsyncCall(function (){
      // Async call is done, alert via callback
      callback();
    });
  },
  // 3rd param is the function to call when everything's done
  function(err){
    // All tasks are done now
    doSomethingOnceAllAreDone();
  }
);

来源:justinklemm.com - Node.js Async tutorial

提示:使用命名函数。

代码

您可以在下面找到我使用的代码:

const dbService = require("./../data/databaseService.js"),
      apiService = require("./../data/apiService.js"),
      express = require("express"),
      async = require("async"),
      router = express.Router();

router.get("/list", (req, res, next) => {

    dbService.getLists((err, data) => {
        if (err) {
            next(err);
        }
        else {
            
            let seriesData = [],
                apiRequests = [];

            for (let listIndex = data.length; listIndex--;) {

                let theName = data[listIndex].name;

                seriesData.push({
                    name: theName,
                    series: []
                });

                for (let seriesIndex = data[listIndex].series.length; seriesIndex--;) {

                    let id = data[listIndex].series[seriesIndex];

                    apiRequests.push({
                        destinationListName: theName,
                        tmdbId: id
                    });
                }
            }

            let apiCall = (apiReq, cb) => {
                apiService.request(`tv/${apiReq.tmdbId}?append_to_response=images,similar`, (err, data) => {
                    if (err) {
                        next(err);
                    }
                    else {
                        for (let listIndex = seriesData.length; listIndex--;) {
                            let name = seriesData[listIndex].name;

                            if (name == apiReq.destinationListName) {
                                seriesData[listIndex].series.push(data);
                                cb();
                            }
                        }
                    }
                });
            },
            afterApiCall = (err) => {
                if (err) {
                    next(err);
                }
                else {
                    res.send(seriesData);
                }
            };

            async.each(apiRequests, apiCall, afterApiCall);
        }
    });
});

module.exports = router;

【讨论】:

    猜你喜欢
    • 2019-02-24
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    相关资源
    最近更新 更多