Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I fire and forget a promise in nodejs (ES7)?

I would like to run this code with babel:

redisClientAsync.delAsync('key');
return await someOtherAsyncFunction();

inside an async function without await the first line. is this OK?

how else can I run something that I don't care?

Can I just fire the non-promisified function del('key',null) without a callback?

like image 844
arisalexis Avatar asked Sep 03 '15 20:09

arisalexis


People also ask

How do you wait for a Promise to finish JavaScript?

The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.

Can I use Promise in Node JS?

A promise is basically an advancement of callbacks in Node. In other words, a promise is a JavaScript object which is used to handle all the asynchronous data operations. While developing an application you may encounter that you are using a lot of nested callback functions.

What happens if you dont await a Promise JavaScript?

Without using await, a promise is returned, which you can use as per need.

How do you handle promises in Node?

The promise is resolved by calling resolve() if the promise is fulfilled, and rejected by calling reject() if it can't be fulfilled. Both resolve() and reject() takes one argument - boolean , string , number , array , or an object .


3 Answers

Yes, you can do that, and it will run the two asynchronous functions in parallel. You've just created a promise and thrown it away.

However, this means that when the promise is rejected you won't notice. You'll just get an unhandledRejection eventually which will crash your process if not handled.

Is this OK? How can I run something that I don't care?

Probably it's not OK. If you truly wouldn't care, you hadn't run it in the first place. So you should be clear and explicit what you care about (and what not):

  • do you want to wait? (for side effects)
  • do you need the result?
  • do you want to catch exceptions?

If you only want to wait and don't care for the result value, you can easily throw away the result:

void (await someAsyncFunction()); // or omit the void keyword,
                                  // doesn't make a difference in an expression statement

If you don't care about exceptions, you can ignore them using

… someAsyncFunction().catch(function ignore() {}) …

You can throw that away, await it, do anything with it.

If you want the result, you have to await it. If you care about exceptions, but don't really want to wait, you may want to execute it in parallel with the following functions:

var [_, res] = await Promise.all([
    someAsyncFunction(), // result is ignored, exceptions aren't
    someOtherAsyncFunction()
]);
return res;
like image 52
Bergi Avatar answered Oct 04 '22 08:10

Bergi


inside an async function without await the first line. is this OK?

Yes, there are cases where you'd want to do this which are perfectly reasonable. Especially where you don't care about the result - one example is an analytics tracking operation that should not interfere with business critical code.

how else can I run something that I don't care?

In many ways, however simply calling the promise function works. Your del without a callback would probably work in this case but some functions don't guard against not passing callbacks, so you can pass an empty function instead (.del('key', () => {})).

You do want to however make sure that you know about it failing, even if you don't want to disrupt the operation of code - so please consider adding a process.on("unhandledRejection', event handler to explicitly ignore these particular exceptions or suppress them via:

redisClient.delAsync('key').catch(()=>{});

Or preferably, something like:

redisClient.delAsync('key').catch(logErr);
like image 21
Benjamin Gruenbaum Avatar answered Oct 04 '22 07:10

Benjamin Gruenbaum


From all the research I've made so far, I think it's fine to do it, as long as you guarantee that the function you are not awaiting for guarantees a way to handle its own errors in case that happens. For example, a try-catch wrapping the whole function body, like you see in the following snippet for the asyncFunction.

It doesn't matter if the function throws synchronously or asynchronously. It guarantees the your mainFunction will complete no matter what. That's the key point here.

If you don't guarantee that, you have to risks:

  • If it throws synchronously, your main function will not complete.
  • If it throws asynchronously, you'll get an unhandled excepction

// THIS IS SOME API CALL YOU DON'T WANT TO WAIT FOR

const mockAPI = () => {
  console.log("From mockAPI");
  return new Promise((resolve,reject) => {
    setTimeout(() => reject("LATE THROW: API ERROR"), 500);
  });
};

// THIS IS THE SOME ASYNC FUNCTION YOU CALL BUT NOT AWAIT FOR

const asyncFunction = async (syncThrow) => {
  try {
    console.log("Async function START");
    if (syncThrow) throw new Error("EARLY THROW");
    await mockAPI();
    console.log("Async function DONE");
  }
  catch(err) {
    console.log("From async function catch");
    console.log(err.message || err);
    return;
  }
};

// THIS IS YOUR MAIN FUNCTION

const mainFunction = async (syncThrow) => {
  try {
    console.clear();
    console.log("Main function START");
    asyncFunction(syncThrow);
    console.log("Main function DONE <<< THAT'S THE IMPORTANT PART");
  }
  catch(err) {
    console.log("THIS WILL NEVER HAPPEN");
    console.log(err);
  }
};
<div>
  <button onClick="mainFunction(true)">Sync throw</button>
  <button onClick="mainFunction(false)">Async throw</button>
</div>
like image 2
cbdeveloper Avatar answered Oct 04 '22 06:10

cbdeveloper