node.js 使用 setInterval 异步等待

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52184291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:54:30  来源:igfitidea点击:

async await with setInterval

node.jspromiseasync-await

提问by Andrey Radkevich

function first(){
  console.log('first')
}
function second(){
  console.log('second')
}
let interval = async ()=>{
  await setInterval(first,2000)
  await setInterval(second,2000)
}
interval();

Imagine that I have this code above.

想象一下,我上面有这段代码。

When I run it, first()and second()will be called at the same time; how do I call second()after first)()returns some data, for example, if first()is done, only then call second()?

当我运行它,first()second()会在同一时间被调用; 返回一些数据second()后如何调用first)(),例如,如果first()完成,然后才调用second()

Because first()in my code will be working with a big amount of data and if this 2 functions will be calling at the same time, it will be hard for the server.

因为first()在我的代码中将处理大量数据,如果这两个函数将同时调用,服务器将很难。

How do I call second()each time when first()will return some data?

second()每次first()返回一些数据时如何调用?

回答by Madara's Ghost

You have a few problems:

你有几个问题:

  1. Promises may only ever resolve once, setInterval()is meant to call the callback multiple times, Promises do not support this case well.
  2. Neither setInterval(), nor the more appropriate setTimeout()return Promises, therefore, awaiting on them is pointless in this context.
  1. Promises 可能只解析一次,setInterval()意味着多次调用回调,Promises 不能很好地支持这种情况。
  2. 无论是setInterval(),还是比较合适setTimeout()的回报的承诺,因此,await荷兰国际集团对他们在这方面毫无意义。

You're looking for a function that returns a Promise which resolves after some times (using setTimeout(), probably, not setInterval()).

您正在寻找一个返回 Promise 的函数,该函数在一段时间后解析(使用setTimeout(),可能,不是setInterval())。

Luckily, creating such a function is rather trivial:

幸运的是,创建这样一个函数相当简单:

async function delay(ms) {
  // return await for better async stack trace support in case of errors.
  return await new Promise(resolve => setTimeout(resolve, ms));
}

With this new delayfunction, you can implement your desired flow:

使用这个新delay功能,您可以实现您想要的流程:

function first(){
  console.log('first')
}
function second(){
  console.log('second')
}
let run = async ()=>{
  await delay(2000);
  first();
  await delay(2000)
  second();
}
run();

回答by mdikici

As mentioned above setIntervaldoes not play well with promises if you do not stop it. In case you clear the interval you can use it like:

如上所述,如果你不阻止它,那么setIntervalPromise 就不会很好地发挥作用。如果您清除了间隔,您可以像这样使用它:

async function waitUntil(condition) {
  return await new Promise(resolve => {
    const interval = setInterval(() => {
      if (condition) {
        resolve('foo');
        clearInterval(interval);
      };
    }, 1000);
  });
}

Later you can use it like

以后你可以像这样使用它

const bar = waitUntil(someConditionHere)

回答by Estus Flask

setIntervaldoesn't play well with promises because it triggers a callback multiple times, while promise resolves once.

setInterval不适合使用 promise,因为它会多次触发回调,而 promise 会解析一次。

It seems that it's setTimeoutthat fits the case. It should be promisified in order to be used with async..await:

似乎它很setTimeout适合这种情况。它应该被promisified以便与async..await

async () => {
  await new Promise(resolve => setTimeout(() => resolve(first()), 2000));
  await new Promise(resolve => setTimeout(() => resolve(second()), 2000));
}

回答by Guanhua Xin

await expression causes async to pause until a Promise is settled

await 表达式导致 async 暂停,直到 Promise 被解决

so you can directly get the promise's result without await

所以你可以直接得到promise的结果而无需等待

for me, I want to initiate Http request every 1s

对我来说,我想每 1 秒发起一次 Http 请求

let intervalid 
async function testFunction() {
    intervalid = setInterval(() => {
        // I use axios like: axios.get('/user?ID=12345').then
        new Promise(function(resolve, reject){
            resolve('something')
        }).then(res => {
            if (condition) {
               // do something 
            } else {
               clearInterval(intervalid)
            }    
        })  
    }, 1000)  
}
// you can use this function like
testFunction()
// or stop the setInterval in any place by 
clearInterval(intervalid)