async await with setInterval
Solution 1
As mentioned above setInterval
does not play well with promises if you do not stop it. In case you clear the interval you can use it like:
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)
Solution 2
You have a few problems:
- Promises may only ever resolve once,
setInterval()
is meant to call the callback multiple times, Promises do not support this case well. - Neither
setInterval()
, nor the more appropriatesetTimeout()
return Promises, therefore,await
ing on them is pointless in this context.
You're looking for a function that returns a Promise which resolves after some times (using setTimeout()
, probably, not 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 delay
function, you can implement your desired flow:
function first(){
console.log('first')
}
function second(){
console.log('second')
}
let run = async ()=>{
await delay(2000);
first();
await delay(2000)
second();
}
run();
Solution 3
setInterval
doesn't play well with promises because it triggers a callback multiple times, while promise resolves once.
It seems that it's setTimeout
that fits the case. It should be promisified in order to be used with async..await
:
async () => {
await new Promise(resolve => setTimeout(() => resolve(first()), 2000));
await new Promise(resolve => setTimeout(() => resolve(second()), 2000));
}
Solution 4
await expression causes async to pause until a Promise is settled
so you can directly get the promise's result without await
for me, I want to initiate Http request every 1s
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)
Andrey Radkevich
Updated on July 09, 2022Comments
-
Andrey Radkevich almost 2 years
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()
andsecond()
will be called at the same time; how do I callsecond()
afterfirst)()
returns some data, for example, iffirst()
is done, only then callsecond()
?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.How do I call
second()
each time whenfirst()
will return some data? -
Benjamin Gruenbaum over 5 years
delay
should be justutil.promisify(setTimeout)
. -
Zhora almost 5 yearsThough I think the question asked isn't clearly stated, this answer points out the fallacy stated by several people that
setInterval
doesn't play well with promises; it can play very well if the correct logic is supplied (just as any code has its own requirements to run correctly). I fixed some syntax errors but I think the gist of this answer provides better information than the others. (I don't think it really answers the original question but I'm not sure I know exactly what that question is asking myself.) -
Long Nguyen about 3 yearsThen condition should be a callback function.
-
WhoIsCarlo about 3 yearsReally appreciate this! Thank you