Node.js依赖的API请求调用使用async.waterfall,并将JSON响应与undercore.extend

Node.js - dependant API request calls using async.waterfall and merge JSON response with underscore.extend

本文关键字:并将 waterfall JSON 响应 extend undercore async 依赖 js API 请求      更新时间:2023-09-26

好吧,这里发生了很多事情,但我试图尽可能地隔离这个问题。

在我的node.jsExpress项目中,我正在进行两个API请求调用,第二个调用依赖于第一个调用。为了让这个任务更容易,我使用了异步模块中的瀑布方法。

getVideoDetails函数中,我将第二个API请求与从第一个响应中检索的videoId进行循环,以获得视频数据。

我目前的问题是,var extended只给我body值,而我希望它是result + body

我想知道这是因为_extend不应该在循环中。我也不清楚如何使结果可访问,以便在循环外调用回调(result)。

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);
});

如果你想按顺序做这些事情。。。

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

那么这是使用异步库可以实现的一种方法。

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);
    })
};