如何在 res.on('end', function () ) {..} 内循环以及 res.on('end) 是如何工作的?
How to loop inside res.on('end', function () ) {..} and how res.on('end) really works?
我试图浏览所有类似的问题,但其中 none 完全回答了我的问题。
我正在尝试使用 rottentomatoes api 来检索与一般标题搜索相对应的电影列表,并显示每个电影的导演。
现在,必须通过单独的 json(对应于电影本身的那个)来获取导演,因此我必须执行 http.request
来获取电影列表,然后,他们每个人,再制作一个 http.request
来获取相应的导演。
问题是当我尝试在第一个 res.on('end' , function(){..})
中循环时,这样对于检索到的每部电影我都可以再做一个 http.request
。
我知道所有请求都是异步的,但这应该不是问题,相反,第一部电影的导演附加到 json object 包含同一第一部电影的导演,当我尝试解析这个 object 我得到一个错误
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.request
的res.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);
});
};
如果您已经找到解决方案,您可能会问,这是什么问题?
首先,我想分享一下,因为它是我的一个朋友建议的,老实说,我从来没有想过在回调函数本身上循环。
其次,我不知道为什么我的选择不起作用。问题出在哪里?
抱歉拖了这么久 post,我尽力解释了一切。如果是 repost,请随时为我指出通往天堂的路。
最大
您可能 运行 遇到了这里提到的问题 closure inside a for loop - callback with loop variable as parameter ,这很常见。
debug/trace 的一种简单方法是使用大量 console.logs 输出变量。这样你就可以看到发生了什么。
另一件有用的事情是使用 request-promise-json
模块,可能还有 async/await
和 babel
。它基本上看起来像这样:
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;
}
我试图浏览所有类似的问题,但其中 none 完全回答了我的问题。
我正在尝试使用 rottentomatoes api 来检索与一般标题搜索相对应的电影列表,并显示每个电影的导演。
现在,必须通过单独的 json(对应于电影本身的那个)来获取导演,因此我必须执行 http.request
来获取电影列表,然后,他们每个人,再制作一个 http.request
来获取相应的导演。
问题是当我尝试在第一个 res.on('end' , function(){..})
中循环时,这样对于检索到的每部电影我都可以再做一个 http.request
。
我知道所有请求都是异步的,但这应该不是问题,相反,第一部电影的导演附加到 json object 包含同一第一部电影的导演,当我尝试解析这个 object 我得到一个错误
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.request
的res.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);
});
};
如果您已经找到解决方案,您可能会问,这是什么问题? 首先,我想分享一下,因为它是我的一个朋友建议的,老实说,我从来没有想过在回调函数本身上循环。 其次,我不知道为什么我的选择不起作用。问题出在哪里?
抱歉拖了这么久 post,我尽力解释了一切。如果是 repost,请随时为我指出通往天堂的路。
最大
您可能 运行 遇到了这里提到的问题 closure inside a for loop - callback with loop variable as parameter ,这很常见。
debug/trace 的一种简单方法是使用大量 console.logs 输出变量。这样你就可以看到发生了什么。
另一件有用的事情是使用 request-promise-json
模块,可能还有 async/await
和 babel
。它基本上看起来像这样:
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;
}