I'm making a web server with Node.js with express and a mongodb . I'll represent some series into a list on the home fragment of my Android application. Something like image below:
The red rectangle is one list with multiple series.
In the database, I've create a collection named lists
. Here is an example of a document:
{
"_id" : ObjectId("486464a459f14e486012ee4a"),
"name" : "Flemish",
"series" : [ 61519, 64095, 11431, 16148, 63315, 68667, 8318, 61548, 62025, 36960 ]
}
The property series
got a different length in each document.
The numbers in that array, are representing ID's from series. They are comming from The Movie Database (TMDb) .
Now I'll merge my list from my database with the data from TMDb. For this, I've made this code:
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;
The problem I've got is that the line res.send(seriesData);
is called before the data is pushed to the array seriesData
. This happen on this line temp.series.push(data);
. Below you find the code that will be send:
[
{
"name": "British",
"series": []
},
{
"name": "American",
"series": []
},
{
"name": "Reality",
"series": []
},
{
"name": "Flemish",
"series": []
}
]
I know everything happens async with Node.js and I haven't been shocked by the result but now Node must wait.
Now my question is, can the response wait till all data is loaded from TMDb? If yes how, else why?
Note also that the items in the lists must be equal. Example: the series "Game of thrones" stands in the American list and can not be pushed to another list. Same thing with the series "Als de dijken breken" . This series stand into the Flemish list and cannot be pushed into British.
I've made an image where you can check the code again and got the results of each request and response as JSON code.
After searching and testing I've finally found a solution.
For library I use Async.js . You can install that by using code below in your command line:
npm install --save async
And added the library by using this
const async = require("async");
I use the async.each()
methode.
This is the simpler solution to the problem. The function takes an array of items, then iterates over them calling a wrapper function which accepts the item as an argument. When all the calls are complete, you specify a final function to be called.
// 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(); } );
Hint: make use of named functions.
Below you can find the code I use:
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;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.