我正在制作一个带有express和mongodb的Node.js的网络服务器。我将把一些系列表示在我的Android应用程序的主片段列表中。如下图所示:
红色矩形是一个包含多个系列的列表。
在数据库中,我创建了一个名为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代码获得。
答案 0 :(得分:0)
经过搜索和测试,我终于找到了解决方案。
对于图书馆,我使用Async.js。您可以在命令行中使用以下代码安装它:
npm install --save async
使用此
添加了库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(); } );
提示:使用命名函数。
您可以在下面找到我使用的代码:
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;