2

Coming from a python async background, in python it's very important to always keep track of async tasks (promises). The runtime gives errors for "floating" async tasks with no references. In Javascript, though, in some cases it seems perfectly OK to just start an async task and not await it or even remember its Promise, for instance if you don't care about its return value and just want it to get executed "later".

Are there guidelines or best practices about when in JS/TS, either in browser or in node.js, it's acceptable to just let an async task go, and not keep a reference to it? Clearly if you care about its return value in the mainline code you have to await it, and similarly if you care that errors are reported before the main function completes. What are other cases and considerations?

To be clear I'm not asking about opinions, I'm asking what are the important things to keep in mind when "firing and forgetting" async tasks (if that's the right term).

GaryO
  • 5,873
  • 1
  • 36
  • 61
  • It is OK not to await for an async task in JavaScript when you don't care about the result of the task, and subsequent code does not depend on the async task having completed (successfully or not). However, you should always make sure to handle errors. – sdgluck Jul 06 '20 at 18:24
  • See [Can I fire and forget a promise in nodejs?](https://stackoverflow.com/q/32384449/1048572) – Bergi Oct 16 '21 at 18:06

2 Answers2

0

Whether and when to do this will be a matter of opinion, so that part is off-topic for Stack Overflow.

But the concrete part is the question of: if you do this, are there any precautions you have to take? And the answer there is: Yes. You need to catch and handle errors.

Consider this fire-and-forget async call that returns a promise:

doSomethingAsync();

If the thing being done can fail, that promise can be rejected. If it's rejected and nothing handles that rejection, then:

  • In a browser, you get an error written to the browser console. 99.9999999% of users won't notice.
  • In Node.js, you get this error written to the console:

(node:26477) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Note that warning: At some point, a future version of Node.js may start *terminating the process when you allow a promise rejection to go unhandled.

So if you fire-and-forget, be sure to catch errors, even if you just silently swallow them:

doSomethingAsync().catch(error => {}); // Obviously only do this if you really don't
                                       // care about the error!

Fun side note: In JavaScript, you have unhandled promise fulfillment all the time. Consider:

doSomethingAsync()
.then(result => {
    // ...do something with result...
})
.catch(error => {
    // ...handle/report the error...
});

Are all the promises handled there?

No. And that's just fine.

Remember that then and catch create and return a promise. The promise returned by catch in the above has no handlers attached to it. That's fine, provided it is only ever fulfilled, not rejected. Nothing ever does anything with that fulfillment. :-)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-2

I think the general concern I would have is, do you have a mechanism to handle errors?

eslint has a no-floating-promises rule that at the very least forces you to add a .catch(), which I think is good.

Evert
  • 93,428
  • 18
  • 118
  • 189
  • I guess this question got closed as "opinion-based", but I was really asking about best practices. @T.J.Crowder's answer was just what I was looking for. Let me see if I can reformulate it. – GaryO Jul 06 '20 at 18:49
  • 1
    Most good questions are opinion based :(. It's a bad rule – Evert Jul 06 '20 at 18:57