I have a function called wait
which accepts time in milliseconds and returns a promise. The promise should get resolved if myEvent
is fired or after some time ms
whichever occurs first. Currently I am doing something like this which I don't think is the right way to do it.
async function wait(ms) {
return new Promise((res) => {
myEmitter.on('myEvent', res);
setTimeout(res, ms);
});
}
Is there a better way to do this?
I have a function called wait
which accepts time in milliseconds and returns a promise. The promise should get resolved if myEvent
is fired or after some time ms
whichever occurs first. Currently I am doing something like this which I don't think is the right way to do it.
async function wait(ms) {
return new Promise((res) => {
myEmitter.on('myEvent', res);
setTimeout(res, ms);
});
}
Is there a better way to do this?
Share Improve this question asked Jan 25, 2021 at 8:11 Aditya DSAditya DS 1032 silver badges9 bronze badges 2- 2 Wouldn't the caller like to know the difference between the event and the timeout? – jfriend00 Commented Jan 25, 2021 at 8:18
- @jfriend00 Not necessary for my use case – Aditya DS Commented Jan 25, 2021 at 8:56
2 Answers
Reset to default 4What you're doing is fine.¹ Once the promise is settled (by the first call to the resolve
function or reject
function, to use their usual names), calling the resolve
/reject
functions again doesn't do anything at all. So what you have is the simple way to write it.
If you were doing something with a side effect like res(doSomethingAndReturnValue())
in the event handler or timeout handler, that wouldn't be a good idea because the doSomethingAndReturnValue()
part still executes and has its side effects. But in your example you aren't doing that.
¹ Three fairly minor notes:
I assume that when your event handler is called, some information is passed to the handler. Since you're using
res
directly as the handler, it will receive that information. So you have it set up to fulfill the promise with the value the event handler gets (if the event fires first), or withundefined
(if the timer fires first), which means the code using it sees varying fulfillment values.Typically I'd expect a timeout to be a rejection rather than a fulfillment, but it depends on your use case.
Your function doesn't need the
async
modifier, because it never usesawait
. A function doesn't needasync
just because it returns a promise. As of a normative change to the spec a year or so back, it no longer makes a difference if you return a native promise from anasync
function as you're doing (it used to delay things very briefly), but there's no reason for it.
Your code is correct. A promise can only be resolved once - if you resolve it twice, the second one is effectively a no-op.
With that said, as an alternative you can use Promise.race
which has the same idea. It takes promises as input and will produce a promise that settles when the first of the input of promises settles.
For example, clicking the button here settles a promise but it also gets settled in 10 seconds:
let buttonResolve;
let buttonPromise = new Promise(res => buttonResolve = res);
document.querySelector("button")
.addEventListener("click", buttonResolve)
let timedPromise = new Promise(res => setTimeout(res, 10000));
let start = Date.now();
Promise.race([buttonPromise, timedPromise])
.then(() => console.log(`finished in ${(Date.now() - start) / 1000}s`))
<button>Click me</button>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745534608a4631848.html
评论列表(0条)