【问题标题】:How to loop inside res.on('end', function () ) {..} and how res.on('end) really works?如何在 res.on('end', function () ) {..} 内部循环以及 res.on('end) 的真正工作原理是什么?
【发布时间】:2015-10-03 09:53:01
【问题描述】:

我试图查看所有类似的问题,但没有一个能完全回答我的问题。

我正在尝试使用 rottentomatoes api 来检索与一般标题搜索相对应的电影列表,并为每个人显示他们的导演。

现在,导演必须通过一个单独的 json(对应于电影本身的那个)来获取,因此我必须做一个 http.request 来获取电影列表,然后为每个人制作另一个 @987654322 @获取对应的导演。

问题是当我尝试在第一个res.on('end' , function(){..}) 中循环时,这样对于检索到的每一部电影我都可以再做一个http.request。 我知道所有请求都是异步的,但这应该不是问题,相反,第一部电影的导演会附加到包含同一部电影导演的 json 对象,当我尝试解析这个对象时,我得到一个错误

undefined:1
.rottentomatoes.com/api/public/v1.0/movies/770687943/similar.json"}}{"id":9272
                                                                    ^

由于两个 json 响应附加到自己,它们不再是 json,因此出现错误。

就好像循环的第一次迭代(获取导向器的那个)被执行了两次。我认为这不应该是 favicon 等的问题。

我通过反复试验发现这种循环方式有效:

function httpGetMovies(response) {
var fullRequestQueryMovie = partialQueryMovie + apiKeyMovie + '&' + queryTermMovie + '&page_limit=2'+'&_prettyprint=true';
console.log('Calling -> ' + fullRequestQueryMovie);

var headersMovie = {
        'Content-Type': 'application/json'
};


var optionsMovie = {
        host: hostMovie,
        path: fullRequestQueryMovie,
        method: 'GET',
        headers: headersMovie
};

var jsonStringResponseMovie = '';

var req = http.request(optionsMovie, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);

    res.on('data', function(piece) {
        jsonStringResponseMovie += piece;
        //console.log("-----------------\n"+jsonStringResponseMovie);
    });

    var i=0;
    res.on('end', function addDirector() {

        var jsonObj = JSON.parse(jsonStringResponseMovie);

        var moviesBag = [];

            console.log("film n°: "+i+" of "+jsonObj.movies.length+" "+jsonObj.movies[i].title);


//              /-----begin nested http.request--------
            var singleMovieDirectors = [];

            var fullRequestSingleMovie = jsonObj.movies[i].links.self + '?apikey=' + apiKeyMovie ;

            var headersSingleMovie = {
                    'Content-Type': 'application/json'
            };

            var optionsSingleMovie = {
                    host: hostMovie,
                    path: fullRequestSingleMovie,
                    method: 'GET',
                    headers: headersSingleMovie
            };

            var jsonStringResponseSingleMovie = '';

            var req2 = http.request(optionsSingleMovie, function(res2) {
                console.log("request for "+optionsSingleMovie.path);
//                  console.log("statusCode: ", res.statusCode);
//                  console.log("headers: ", res.headers);

                res2.on('data', function(piece2) {
                    jsonStringResponseSingleMovie += piece2;
                });

                res2.on('end', function() {

                    var jsonObjSingleMovie = JSON.parse(jsonStringResponseSingleMovie);
                    console.log("directors > "+JSON.stringify(jsonObjSingleMovie.abridged_directors));
                    // response.send(blabla);

                if (i++ < jsonObj.movies.length-1){
                    addDirector()
                }
                    else{
                        console.log ("finished adding directors");
                    }

                });
            });

            req2.end();

            req2.on('error', function(e) {
                console.error(e);
            });

//              -------end of nested http.request-----------------




    });

});

req.end();

req.on('error', function(e) {
    console.error(e);
});


};

您可以看到在主http.requestres.on('end') 之前有一个i=0,并且里面有一个嵌套请求,如果还有任何电影,则在其末尾带有一个检查和增量i ,我将再次调用回调函数,但使用 i++ ,从而转移到下一部电影。 注意这个调用#movies是回调函数的倍数

相反,这种方式不起作用,我不知道为什么

function httpGetMovies(response) {
 var fullRequestQueryMovie = partialQueryMovie + apiKeyMovie + '&' + queryTermMovie + '&page_limit=2'+'&_prettyprint=true';
console.log('Calling -> ' + fullRequestQueryMovie);

var headersMovie = {
        'Content-Type': 'application/json'
};


var optionsMovie = {
        host: hostMovie,
        path: fullRequestQueryMovie,
        method: 'GET',
        headers: headersMovie
};

var jsonStringResponseMovie = '';

var req = http.request(optionsMovie, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);

    res.on('data', function(piece) {
        jsonStringResponseMovie += piece;
        //console.log("-----------------\n"+jsonStringResponseMovie);
    });


    res.on('end', function () {

        var jsonObj = JSON.parse(jsonStringResponseMovie);

        var moviesBag = [];

        for(i = 0; i<sonObj.movies.length-1; i++){

            console.log("film n°: "+i+" of "+jsonObj.movies.length+" "+jsonObj.movies[i].title);


//              /-----begin nested http.request--------
            var singleMovieDirectors = [];

            var fullRequestSingleMovie = jsonObj.movies[i].links.self + '?apikey=' + apiKeyMovie ;

            var headersSingleMovie = {
                    'Content-Type': 'application/json'
            };

            var optionsSingleMovie = {
                    host: hostMovie,
                    path: fullRequestSingleMovie,
                    method: 'GET',
                    headers: headersSingleMovie
            };

            var jsonStringResponseSingleMovie = '';

            var req2 = http.request(optionsSingleMovie, function(res2) {
                console.log("request for "+optionsSingleMovie.path);
//                  console.log("statusCode: ", res.statusCode);
//                  console.log("headers: ", res.headers);

                res2.on('data', function(piece2) {
                    jsonStringResponseSingleMovie += piece2;
                });

                res2.on('end', function() {

                    var jsonObjSingleMovie = JSON.parse(jsonStringResponseSingleMovie);
                    console.log("directors > "+JSON.stringify(jsonObjSingleMovie.abridged_directors));
                    // response.send(blabla);



                });
            });

            req2.end();

            req2.on('error', function(e) {
                console.error(e);
            });

//              -------end of nested http.request-----------------

        } // end of for loop


    });

});

req.end();

req.on('error', function(e) {
    console.error(e);
});


};

如果您已经找到解决方案,您可能会问,问题是什么? 首先,我想分享一下,因为这是我的一个朋友建议的,老实说,我从来没有想过在回调函数本身上循环。 其次,我不知道为什么我的选择不起作用。问题出在哪里?

抱歉,这篇文章很长,我试图解释一切。如果是转发,请随时为我指出通往天堂的道路。

最大。

【问题讨论】:

    标签: javascript node.js express callback


    【解决方案1】:

    您可能会遇到这里提到的问题closure inside a for loop - callback with loop variable as parameter ,这很常见。

    调试/跟踪的一种简单方法是使用大量 console.log 输出变量。这样你就可以看到正在发生的事情。

    另一件有帮助的事情是使用request-promise-json 模块,可能还有async/awaitbabel。它基本上看起来像这样:

      async function checkMovies(movies) {
        let result = [];
        for (let title of movies) {
          let movie = await request(`${base}?${movie}.json`);
          let movie.director = await request(`${base}${movie.director}.json`);
          result.push(movie);
        }
        return result;
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2011-11-08
      • 1970-01-01
      相关资源
      最近更新 更多