Node.js – appels d'appel API dépendants utilisant async.waterfall et fusion de la réponse JSON avec underscore.extend

D'accord, il se passe un peu ici, mais j'ai essayé d'isoler le problème autant que possible.

Dans mon projet node.js Express, je fais deux appels de demande d'API pour que le second appel dépend du premier. Pour rendre cette tâche plus facile, j'utilise la méthode waterfall à partir d'un module asynchrone.

Dans la fonction getVideoDetails , j'ai mis la deuxième requête API en boucle avec le videoId partir de la première réponse pour obtenir des données vidéo.

Le problème que j'ai actuellement est que, var extended ne me donne que body valeur du body alors que je m'attend à ce qu'il soit result + body .

Je me demande que c'est parce que _extend ne devrait pas être dans la boucle. Je ne suis pas non plus clair comment je peux rendre le résultat accessible au rappel d'appel (résultat) en dehors de la boucle.

 async.waterfall([ function getVideos (getVideoCallback) { ... }, function getVideoDetails (result, getVideoDetailsCallback) { var urls = []; Object.keys(result.items).forEach(function(item) { urls.push ("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=" + result.items[item].contentDetails.videoId + "&key=xxx"); }) urls.forEach(function(url) { request( url, function(err, response, body) { if(err) { console.log(err); return; } body = JSON.parse(body); var extended = _.extend(result, body); getVideoDetailsCallback(null, extended); }); }); } ], function (err, result) { if (err) { console.log(err); return; } callback(result); }); 

Si vous voulez faire ces choses en ordre …

1. Generate an array asynchronously
2. Do some asynchronous process for each item in the array
3. Do something asynchronous after you have processed the array

… alors c'est une façon de le faire avec la bibliothèque asynchrone.

 var request = require("request"); var _ = require("lodash"); var db = require("whatever you are using"); module.exports = function(req, res) { var params = req.params; async.waterfall([ function getVideos(next) { db.findAll().then(function(rows) { next(null, rows); }); }, function forEachVideoDoSomethingAsync(videos, next) { var urls = videos.map(function(obj) { obj.url = obj.name + "http://googleapi.com/whatever"; return obj; }); /** this is the part you are missing **/ //async.map takes three arguments //1. the array you want to work on //2. a function that is applied to each item in the array // the iterator function receives two arguments // 1. the current item in the array // 2. a callback you invoke when you want to move to the next item //3. a callback that is executed once the loop has been completed async.map(urls, function(currentItem, callback) { request(currentItem.url, function(err, response, body) { if (err) return console.log(error); //you probably have to extend the current item in the array with the response object var json = JSON.parse(body); var extended = _.extend(currentItem, json); //each item you send via the callback will be pushed into the result of async.map callback(extended); }); }, function(err, urls_extended) { //urls_extended is now an array of extended items //now you have to exit the waterfall next(null, urls_extended); }); } ], function(err, urls_extended) { if (err) return console.log(err); //exit the entire process res.send(urls_extended); }) };