deno_std
deno_std copied to clipboard
`assertPromiseResolved()`
Is your feature request related to a problem? Please describe.
During tests I often want to verify that a promise has been resolved right at this moment.
Describe the solution you'd like
This is a function that I've been using a lot for this:
/**
* Asserts whether a promise is currently resolved or not. The check is made asynchronously.
* The call waits for the next event loops and gives the promise a chance to resolve in the current event loop.
* The reason for this is that there is no way to synchronously check the resolved state of promises in JavaScript.
* @param {Promise<any>} promise
* @param {boolean} expected
*/
export async function assertPromiseResolved(promise, expected) {
let resolved = false;
(async () => {
await promise;
resolved = true;
})();
await waitForMicrotasks();
const msg = expected ? "Expected the promise to be resolved" : "Expected the promise to not be resolved";
assert(resolved == expected, msg);
}
waitForMicrotasks
is a very basic:
export function waitForMicrotasks() {
return new Promise(r => setTimeout(r, 0));
}
As far as I'm aware this is required, there's no way to figure out the state of promises synchronously.
Is this something that would be suitable for deno_std? I've got a few tests for this as well.
Describe alternatives you've considered
Keep using this from my own repository ¯\_(ツ)_/¯
@iuioiua any thoughts?
~~What's wrong with asserting the value of the resolved promise? Am I missing something here?~~ Nevermind. I see it now.
await waitForMicrotasks()
part in the above example looks inaccurate to me (it looks waiting more than microtasks). The suggested util (promiseState
) in this stackoverflow answer looks more general (supporting rejected state) and simpler.
The await waitForMicrotasks()
is there because half of the time you need to do that anyway, and when you don't, the extra setTimeout()
isn't really an issue. I haven't really run across a case where I needed to know whether a promise was resolved right at this moment.
I figured without this, you'd just be confused as to why your promise isn't resolved. Only to realise after debugging for a good few minutes that you need to wait for microtasks.
Some stats: 28 of my tests use assertPromiseResolve()
at least once, 12 of which fail without the waitForMicrotasks()
call.
I have also tried
export function waitForCurrentMicroTasks() {
return new Promise(r => queueMicrotask(r));
}
But that still makes 5 of these tests fail.
Being able to check for a rejected state sounds nice though. I usually just use assertRejects()
for that since it also allows you to verify the error message.