I am trying to make a number of GET requests to a webserver using Axios and Node. I use an asynchronous function to take an array of values, to make requests to unique URLs on the same website.
我正在尝试使用Axios和Node向Web服务器发出大量GET请求。我使用异步函数来获取值数组,以便在同一网站上发出对唯一URL的请求。
Each time the loop runs, I push the response to an array called "results."
每次循环运行时,我都会将响应推送到一个名为“results”的数组。
When the loop finishes, the asynchronous function ends, and I tack on a .then
function, passing it the returned value. I then log that to the screen.
当循环结束时,异步函数结束,我在.then函数上执行,并将返回的值传递给它。然后我将其记录到屏幕上。
My problem is that the return statement fires before my requests are run. In other words, an empty array is logged, and then all of the requests are completed.
我的问题是在我的请求运行之前会触发return语句。换句话说,记录一个空数组,然后完成所有请求。
How do I only return the results of my for loop to the asynchronous function after the GET requests are completed, and the array is filled with values?
在GET请求完成后,如何仅将for循环的结果返回到异步函数,并且数组中填充了值?
Thanks for your help, here is the code:
感谢您的帮助,以下是代码:
const axios = require("axios");
var loop = [about,home,products,thanks]
var i;
const results = [];
const test = async () => {
for(i = 0; i < loop.length; i++) {
axios.get(`https://examplewebsite.com/${loop[i]}`)
.then((response,body) => {
results.push(response);
})
.catch((error) => {
console.log(error)
});
};
// THIS IS NOT CORRECT, IT CAUSES MY RESULTS TO BE RETURNED IMMEDIATELY
return results;
}
test().then((results) => {
console.log(results); // Currently outputs --> [ ]
});
1 个解决方案
#1
2
My problem is that the return statement fires before my requests are run. In other words, an empty array is logged, and then all of the requests are completed.
我的问题是在我的请求运行之前会触发return语句。换句话说,记录一个空数组,然后完成所有请求。
You're not keeping reference to each of the Promise Chains you've created with axios.get()
so you can't await them.
您没有保留对使用axios.get()创建的每个Promise链的引用,因此您无法等待它们。
Post initialization, the above code executes like this:
发布初始化后,上面的代码执行如下:
- Call
test()
- 通话测试()
- Iterate and create each request with
axios.get()
- 使用axios.get()迭代并创建每个请求
- Return
results
- 返回结果
-
.then((results) => console.log(results)
is invoked andresults
are printed as[]
- .then((results)=> console.log(results)被调用,结果打印为[]
- Process checks if any async work is being awaited - Nothing is being awaited
- 进程检查是否正在等待任何异步工作 - 没有等待任何事情
- Process exits
- 流程退出
It would've taken at least the next turn of the Event Loop for even one of your requests to have been handled. However, since your code executes in a single turn of the even loop, it runs all the code you wrote except the response handler attached to axios.get()
. If you want to a more detailed explanation of what happens on each turn of the Event Loop and how it all works, you can read more about it here.
即使您的一个请求已被处理,它至少会在事件循环的下一个转弯处进行。但是,由于您的代码在偶数循环的单圈中执行,它会运行您编写的所有代码,但附加到axios.get()的响应处理程序除外。如果您想更详细地解释事件循环每回合发生的事情以及它们如何工作,您可以在这里阅读更多相关信息。
You need to return a reference to each Promise returned from axios.get()
. Instead of storing their responses in an Array, store the Promises from axios.get()
. Even though you're using async/await
syntax, you still need to use Promise.all()
to await more than one Promise at a once. Promise.all()
can be used to await all of the request promise chains stored in your Array.
您需要返回对axios.get()返回的每个Promise的引用。而不是将它们的响应存储在Array中,而是存储来自axios.get()的Promises。即使你使用async / await语法,你仍然需要使用Promise.all()来等待一次多个Promise。 Promise.all()可用于等待存储在Array中的所有请求承诺链。
The above can be written more concisely using Array#map
to iterate over a list of items and return an Array of Promise results.
使用Array#map可以更简洁地编写以上内容,以迭代项列表并返回Promise数组结果。
const axios = require("axios");
const baseURL = 'http://examplewebsite.com/'
const requestList = items => Promise.all(
items.map(key => (
axios.get(`${baseUrl}${key}`)
.catch(err => console.error(err))
)
)
requestList(['about', 'home', 'products', 'thanks'])
.then(results => console.log(result))
.catch(err => console.error(err))
#1
2
My problem is that the return statement fires before my requests are run. In other words, an empty array is logged, and then all of the requests are completed.
我的问题是在我的请求运行之前会触发return语句。换句话说,记录一个空数组,然后完成所有请求。
You're not keeping reference to each of the Promise Chains you've created with axios.get()
so you can't await them.
您没有保留对使用axios.get()创建的每个Promise链的引用,因此您无法等待它们。
Post initialization, the above code executes like this:
发布初始化后,上面的代码执行如下:
- Call
test()
- 通话测试()
- Iterate and create each request with
axios.get()
- 使用axios.get()迭代并创建每个请求
- Return
results
- 返回结果
-
.then((results) => console.log(results)
is invoked andresults
are printed as[]
- .then((results)=> console.log(results)被调用,结果打印为[]
- Process checks if any async work is being awaited - Nothing is being awaited
- 进程检查是否正在等待任何异步工作 - 没有等待任何事情
- Process exits
- 流程退出
It would've taken at least the next turn of the Event Loop for even one of your requests to have been handled. However, since your code executes in a single turn of the even loop, it runs all the code you wrote except the response handler attached to axios.get()
. If you want to a more detailed explanation of what happens on each turn of the Event Loop and how it all works, you can read more about it here.
即使您的一个请求已被处理,它至少会在事件循环的下一个转弯处进行。但是,由于您的代码在偶数循环的单圈中执行,它会运行您编写的所有代码,但附加到axios.get()的响应处理程序除外。如果您想更详细地解释事件循环每回合发生的事情以及它们如何工作,您可以在这里阅读更多相关信息。
You need to return a reference to each Promise returned from axios.get()
. Instead of storing their responses in an Array, store the Promises from axios.get()
. Even though you're using async/await
syntax, you still need to use Promise.all()
to await more than one Promise at a once. Promise.all()
can be used to await all of the request promise chains stored in your Array.
您需要返回对axios.get()返回的每个Promise的引用。而不是将它们的响应存储在Array中,而是存储来自axios.get()的Promises。即使你使用async / await语法,你仍然需要使用Promise.all()来等待一次多个Promise。 Promise.all()可用于等待存储在Array中的所有请求承诺链。
The above can be written more concisely using Array#map
to iterate over a list of items and return an Array of Promise results.
使用Array#map可以更简洁地编写以上内容,以迭代项列表并返回Promise数组结果。
const axios = require("axios");
const baseURL = 'http://examplewebsite.com/'
const requestList = items => Promise.all(
items.map(key => (
axios.get(`${baseUrl}${key}`)
.catch(err => console.error(err))
)
)
requestList(['about', 'home', 'products', 'thanks'])
.then(results => console.log(result))
.catch(err => console.error(err))