I have this function to play audio using a given source and it works fine:
function sfxPlay(source) {
let sfxAudio = new Audio(`${source}`);
sfxAudio.crossOrigin = "anonymous";
sfxAudio.play();
return new Promise((resolve) => {
sfxAudio.addEventListener("ended", function () {
sfxAudio.currentTime = 0;
resolve();
});
});
}
I will use it inside an async function like this:
await sfxPlay(source.mp3);
The question is what if I want to use the function without await
? Does this make any errors if later I use it with await again... what happens to that promise when we don't await for it?!
EDIT: I mean if we have the function like this inside function A:
sfxPlay(source.mp3);
Is it acceptable to use it inside function B like this?
await sfxPlay(source.mp3);
The promise is rejected.
You must await , or you'll get a promise instead of the value you expect. That said, this can be a good thing if you actually want a promise. It gives us more control to do cool stuff like memoizing promises.
Promise.all fail-fast behaviorPromise.all is rejected if any of the elements are rejected. For example, if you pass in four promises that resolve after a timeout and one promise that rejects immediately, then Promise.all will reject immediately.
A Promise that is resolved with the given value, or the promise passed as value, if the value was a promise object. It may be either fulfilled or rejected — for example, resolving a rejected promise will still result in a rejected promise.
If you don't use await, you can still use the promise, you just have to wait on it manually using .then
(the promise is just returned as a normal object):
sfxPlay(source).then(()=>{
// ...
});
Otherwise, if you don't use it, nothing good or bad will happen by default - the code inside the promise will still run, but nothing will happen when you call resolve
.
If you call reject
, however, then nothing will handle the rejection; which is bad, as it throws an error on most platforms. So make sure you never use reject
unless you have a matching .catch
for it (note also that a try
/ catch
statements don't work for this particular type of error). Thanks to @T.J. Crowder for pointing this out.
You can mix the two methods without any issues.
If you just call the function and don't do anything with the promise it returns, it means the result of it settling is never handled, which can be fine or can be a problem. There are three things that can happen with the promise (whether you handle them or not):
The promise never settles, in which case it doesn't matter that you don't handle fulfillment or rejection since neither of them occurs. :-)
The promise is fulfilled. In that case, there's no problem at all. It's just like calling a function and not using its return value.
The promise is rejected. This is just like not handling an exception that's thrown (at all, not in the function itself and not in the function(s) that call it, leaving the exception to work its way up to the host environment). At a minimum, the host will report an "unhandled rejection" to the console or output. Some hosts may terminate your program at that point. For instance, the current (as of this edit) version of Node.js (v17.1.0) terminates the process when an unhandled rejection occurs (though there is a global way to handle otherwise-unhandled rejections). You may not be using Node.js, but it's not the only host that may start handling unhandled rejections this way.
So you probably want to use the promise, at least to catch errors. If your call is in an async
function, await
will do that — but will also hold up the settlement of the promise from the async
function the await
is in. In a non-async
function, or in an async
function where you don't want to wait for settlement, use catch
on the promise:
sfxPlay(source).catch(()=>{
/* ...handle/report the error (or just suppress it, if that's appropriate
[which it sometimes, though rarely, is])...
*/
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With