简体   繁体   English

如何在 javascript 的 for 循环中使用异步等待

[英]How to use async await in for loops in javascript

Basically I have a function which loops through all the elements from an api and pushes it to a array and then I return the array, but I am getting random of amount of elements everytime I run this function.基本上我有一个 function 循环遍历 api 中的所有元素并将其推送到一个数组然后我返回数组,但是每次我运行这个 ZC1C425268E68385D1ABZ507 时我都会随机获得元素数量。

 function getElements() { const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber="; var elements = []; for(var i=1;i<=118;i++){ newurl = url+i.toString(); fetch(newurl).then(response => response.json()).then(data => elements.push(data.symbol)) } return elements; } console.log(getElements());

thanks in advance提前致谢

You need to push entire promise to array and wait for them all to be resolved, so they will be resolved in parallel.您需要将整个 promise 推入阵列并等待它们全部解决,因此它们将并行解决。

 function getElements() { const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber=" const elements = [] for(let i=1;i <= 118; i++){ newurl = url + i // no need to 'i.toString()' elements.push( // push entire promise, not just "unpacked" response fetch(newurl).then(response => response.json()).then(data => data.symbol) ) } return Promise.all(elements) } getElements().then(elements => { console.log(elements.length) console.log(elements) })
 .as-console-wrapper { max-height: 100%;important: top; 0; }

All the promises stored in elements will resolve together using Promise.all() method.存储在elements中的所有承诺将使用Promise.all()方法一起解决。

function getElements() {
    const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber=";
    var elements = [];
    for(var i=1;i<=118;i++){
        newurl = url+i.toString();
        const res = fetch(newurl)
        .then(response => response.json());
        elements.push(res);
    }
    return Promise.all(elements);
}

Do not send so many request at a same time, send request in batches... Wait for 10 promise to finish, then next 10, then next 10, so on...不要同时发送这么多请求,分批发送请求...等待10个promise完成,然后下一个10个,然后下一个10个,以此类推...

 async function getElements() { const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber="; let elements = [], pending = []; for(let i=1; i <= 118; i++){ let p = fetch(url + i).then(response => response.json()).then(data => elements.push(data.symbol)).catch(console.log); if (pending.push(p) > 10) { await Promise.all(pending); pending = []; } } return Promise.all(pending).then(() => elements); } // you cannot use async await in global scope, so I used 'then' here instead getElements().then(elements => console.log(elements.length))

Ok, here you go then (I have limited the number of calls to 3, to not hammer this poor server too much)好的,那么这里是 go(我将调用次数限制为 3,以免过多地敲打这个可怜的服务器)

 const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber="; const getElements = async () => { let elements = []; for(var i=1;i<=3;i++){ newurl = url+i.toString(); const response = await fetch(newurl); const data = await response.json() elements.push(data.symbol) } return elements; // This is a Promise of array, not an array, because an async function always returns a Promise of something. So this can be awaited. }; (async () => { console.log(await getElements()); })();

You can send all requests at once and store the promises in an array.您可以一次发送所有请求并将承诺存储在一个数组中。 Then you can wait for all promises to resolve:然后你可以等待所有的 Promise 解决:

 async function getElements() { const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber="; const promises = []; for(var i=1;i<=118;i++){ newurl = url+i.toString(); promises.push(fetch(newurl)); } return Promise.all(promises); } (async () => { const responses = await getElements(); responses.forEach(async response => console.log(await response.json())); })();

A server should be able to handle 118 requests at once but you shouldn't send too many requests.服务器应该能够同时处理 118 个请求,但您不应该发送太多请求。

Be aware that in this minimal example the order of the console.log usually is not the order you sent the requests.请注意,在这个最小示例中,console.log 的顺序通常不是您发送请求的顺序。 forEach doesn't consider await s. forEach不考虑await

The minimal rule of using async and await is that await can be used in an async function.使用asyncawait的最小规则是await可以在async function 中使用。 So if you don't care about parallelism, you can just wrap your entire test into a bigger async function, add the keywords here and there, and that's it:因此,如果您不关心并行性,您可以将整个测试包装到更大的async function 中,在这里和那里添加关键字,就是这样:

 async function main() { // <-- wrapper async function getElements() { // <-- became async, so can use await const url = "https://neelpatel05.pythonanywhere.com/element/atomicnumber?atomicnumber="; var elements = []; for(var i=1;i<=118;i++){ newurl = url+i.toString(); await fetch(newurl) // <-- await request right in the loop.then(response => response.json()).then(data => elements.push(data.symbol)) } return elements; } console.log(await getElements()); // <-- await the async function } main(); // <-- call wrapper console.log("; results will come after this line !"); // memo about the test still being async

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM