我有一个想要循环的值数组。这些值中的每一个都将用于向服务器发出 http 请求。我将从服务器收到每个请求的响应。我想将所有这些响应存储在一个数组中,然后在 ALL 请求完成后对数组进行处理。由于我的代码的异步性质,我不确定如何使应用程序等待所有请求完成。发生的情况是我正在发出请求,但由于异步性质,我想要对数组执行的工作在所有请求完成之前就已经开始了。我怎样才能使这段代码“同步”,因为它会等到所有请求完成后才开始使用 listOfResponses 数组
//import the require library to make http requests to a server
const request = require('request');
//values to be sent via a restful GET request
const list = [
'value_one',
'value_two'
];
//store resoonses from GET request
var listOfResponses = [];
//loop through the list
list.forEach(function(word) {
//Make a rest GET call to a server
var url = 'http://notsurehowtomakethisworksoiamaskingstackoverflow.com/api/words/' + word;
request(url, {
json: true
}, (err, res, body) => {
if (err) {
return console.log(err);
}
//store the response from the server into out array
listOfResponses.push(body.response);
});
});
/* *******************************
HERE I WANT TO DO STUFF WITH listOfResponses ONCE ALL THE REQUESTS FINISH
********************************** */
只需将其映射到一系列承诺:
const promises = list.map(word => new Promise(resolve => {
var url = 'http://notsurehowtomakethisworksoiamaskingstackoverflow.com/api/words/' + word;
request(url, {
json: true
}, (err, res) => {
if (err) {
return reject(err);
}
resolve(res.body);
});
}));
然后你可以使用
Promise.all
获得所有结果:
Promise.all(promises).then(results => {
//...
});
每次请求结束时只需检查响应:
//import the require library to make http requests to a server
const request = require('request');
//values to be sent via a restful GET request
const list = [
'value_one',
'value_two'
];
//store resoonses from GET request
var listOfResponses = [];
//loop through the list
list.forEach(function(word) {
//Make a rest GET call to a server
var url = 'http://notsurehowtomakethisworksoiamaskingstackoverflow.com/api/words/' + word;
request(url, {
json: true
}, (err, res, body) => {
if (err) {
return console.log(err);
}
//store the response from the server into out array
listOfResponses.push(body.response);
check();
});
});
// CHECK THE LIST
function check() {
if (listOfResponses.length == list.length) {
console.log("YAY! Here you have your responses", listOfResponses);
}
}
这是一个异步场景,实现此目的的一种方法是递归调用一个函数,该函数将循环遍历您的
list
单词。递归根据服务器的每个响应进行。
另一种方法是使用 Promise。
看这个代码片段(递归方法):
//import the require library to make http requests to a server
const request = require('request');
//values to be sent via a restful GET request
const list = [
'value_one',
'value_two'
];
//store resoonses from GET request
var listOfResponses = [];
//loop through the list
var loop = function(array, index, cb) {
if (index === array.length)
cb();
return;
//Make a rest GET call to a server
var url = 'http://notsurehowtomakethisworksoiamaskingstackoverflow.com/api/words/' + array[i];
request(url, {
json: true
}, (err, res, body) => {
if (err) {
return console.log(err);
}
//store the response from the server into out array
listOfResponses.push(body.response);
loop(array, i++, cb);
});
};
loop(list, 0, function() {
/* *******************************
HERE I WANT TO DO STUFF WITH listOfResponses ONCE ALL THE REQUESTS FINISH
********************************** */
});
如您所见,循环从使用
loop
调用 index = 0
函数开始,每个响应都将调用具有递增索引的 loop
函数。
当
index == list.length
时递归结束,并执行回调以保持逻辑流程。
2023 年,我写了 sync-request-curl。该库将帮助使用 libcurl 的 Easy 界面发送同步 HTTP 请求。
该库包含原始 sync-request 中功能的子集,但利用 node-libcurl 以获得更好的性能和 NodeJS 的附加 libcurl 选项。
这是 GET 请求的简单用法:
// import request from 'sync-request-curl';
const request = require('sync-request-curl');
const response = request('GET', 'https://ipinfo.io/json');
console.log('Status Code:', response.statusCode);
console.log('body:', response.body.toString());
console.log('json:', JSON.parse(response.body.toString());
这是一个更接近您的用例的示例:
const request = require('sync-request-curl');
const list = [
'1',
'2',
'3',
];
const listOfResponses = [];
list.forEach((word) => {
const url = `https://dummyjson.com/products/${word}`;
console.log(url);
const response = request('GET', url);
if (response.statusCode === 200) {
const jsonBody = JSON.parse(response.body.toString('utf-8'));
listOfResponses.push(jsonBody.title);
} else {
console.error(`Error for word '${word}': ${response.statusCode}`);
}
});
console.log(listOfResponses);
这给了我们预期的结果:
https://dummyjson.com/products/1
https://dummyjson.com/products/2
https://dummyjson.com/products/3
[ 'iPhone 9', 'iPhone X', 'Samsung Universe 9' ]
希望这有帮助:)。