简体   繁体   English

NodeJS 等待循环完成(异步/等待/承诺)

[英]NodeJS wait for loop to finish (async / await / promisse)

I'm trying to make a loop fetching some info in an API, first I need this loop for to wait for the request to finish and after continue for the next array value, after the loop finish, then I need it to call that function again every 5 seconds, but only after the previous call ends.我正在尝试创建一个循环来获取API中的一些信息,首先我需要这个循环来等待请求完成并在继续下一个数组值之后,在循环完成后,我需要它来调用该函数每 5 秒再次,但仅在前一个呼叫结束后。

Something like this:像这样的东西:

let ids = [1, 2];

async function getInfoAPI(ids) {

   for (const id of ids){
      const apiInfo = await fetch(`https://apiurl/${id}`);
      const infoJSON = await apiInfo.json();

      //Do more things here
   }
}

Now I need to call the function and wait for the loop to finish.现在我需要调用该函数并等待循环完成。 After the loop is completed then wait for 5 seconds and call the getInfoFromAPI function again.循环完成后等待 5 秒,然后再次调用 getInfoFromAPI 函数。 I tried setInterval but if the loop, for some reason, takes more than 5 seconds to respond, the getInfoFromAPI will be called again even if it didn't finish the previous loop.我尝试了 setInterval 但如果循环由于某种原因需要超过 5 秒的响应时间,即使它没有完成前一个循环,也会再次调用 getInfoFromAPI。

setInterval(function(){ 
        getInfoAPI(ids);
}, 5000);

Is there any way I could do that using promises or something like that?有什么办法可以使用承诺或类似的东西来做到这一点?

Thanks谢谢

You can do something like this:你可以这样做:

function run() {
    getInfo(...).then(() => {
        setTimeout(run, 5000)
    });
}

run().catch(err => {
   console.log(err);
});

Or, I prefer using a promise version of setTimeout() .或者,我更喜欢使用setTimeout()的承诺版本。 I the latest version of nodejs, you can use timersPromises.setTimeout() and it returns a promise:我是最新版本的 nodejs,您可以使用timersPromises.setTimeout()并返回一个承诺:

import { setTimeout } from 'timers/promises';

async function run() {
    await getInfo(...)
    await setTimeout(5000);
    return run();
}

run().catch(err => {
   console.log(err);
});

Or, use a while loop with await :或者,使用带有awaitwhile循环:

import { setTimeout } from 'timers/promises';

async function run() {
    while (true) {
        await getInfo(...)
        await setTimeout(5000);
    }
}

run().catch(err => {
   console.log(err);
});

You can achieve this by importing the promise based setTimeout that ships with NodeJs 16+ and using it as follows:您可以通过导入 NodeJs 16+ 附带的基于 promise 的setTimeout并按如下方式使用它来实现这一点:

Import:进口:

import { setTimeout } from "timers/promises"

Use:利用:

while (true) {
  await getInfoAPI(ids);
  await setTimeout(5000);
}

Use recursion:使用递归:

async function getInfoPeriodically() {
  await getInfoAPI(ids);
  setTimeout(() => {
    getInfoPeriodically()
  }, 5000);
}

You can add the parameters to customize this function/pass values in but this is the idea.您可以添加参数来自定义此函数/传入值,但这就是想法。

Why don't you try to use Promise.all or Promise.allSettled ?为什么不尝试使用Promise.allPromise.allSettled With that you can use concurrency to fetch all the data at once, instead that one by one.有了它,您可以使用并发来一次获取所有数据,而不是一个一个地获取。 In case you need to do it one by one, I suggest you to use for-await...of .如果你需要一个一个地做,我建议你使用for-await...of

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

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