Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference of using async / await vs promises?

Tags:

I am looking for a answer on what to use in my nodeJS app.

I have code which handles my generic dB access to mssql. This code is written using an async functions and then I used a promise to call that function and all works fine.

As my app is getting bigger and code larger I am planning to move some of the logic into functions and then call them.

So my question is: is there a drawback to using a mix of async/await and promises or does it really not matter?

Async / await makes it easier to write more readable code as I have to read and write to multiple db’s before I return something and I need results of some of these.

So the question is what is the better approach? Async / await on dB layer that’s set and can’t change The logic layer async / await which would allow me a async / and await on the function call or if I go with promise for logic then I am stuck with promise on function call.

So I hope someone can give me more insight if one has more advantages than the other, besides being able to write cleaner code.

like image 363
MisterniceGuy Avatar asked Oct 30 '18 03:10

MisterniceGuy


People also ask

What is difference between async and await?

The async keyword is used to define an asynchronous function, which returns a AsyncFunction object. The await keyword is used to pause async function execution until a Promise is fulfilled, that is resolved or rejected, and to resume execution of the async function after fulfillment.

Which is faster promise or async await?

Yes, you read that right. The V8 team made improvements that make async/await functions run faster than traditional promises in the JavaScript engine.

Do you need promise with async await?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.


1 Answers

async/await and promises are closely related. async functions return promises, and await is syntactic sugar for waiting for a promise to be resolved.

The only drawback from having a mix of promises and async functions might be readability and maintainability of the code, but you can certainly use the return value of async functions as promises as well as await for regular functions that return a promise.

Whether you choose one vs the other mostly depends on availability (does your node.js / browser support async?) and on your aesthetic preference, but a good rule of thumb (based on my own preference at the time of writing) could be:

If you need to run asynchronous code in series: consider using async/await:

return asyncFunction() .then(result => f1(result)) .then(result2 => f2(result2)); 

vs

const result = await asyncFunction(); const result2 = await f1(result); return await f2(result2); 

If you need nested promises: use async/await:

return asyncFunction() .then(result => {   return f1(result)   .then(result2 => f2(result, result2); }) 

vs

const result = await asyncFunction(); const result2 = await f1(result); return await f2(result, result2); 

If you need to run it in parallel: use promises.

return Promise.all(arrayOfIDs.map(id => asyncFn(id))) 

It has been suggested you can use await within an expression to await multiple tasks like so:
*note, this still awaits in sequence from left to right, which is OK if you don't expect errors. Otherwise the behaviour is different due to fail fast behaviour of Promise.all()

const [r1, r2, r3] = [await task1, await task2, await task3]; 

(async function() {    function t1(t) {      console.time(`task ${t}`);      console.log(`start task ${t}`);      return new Promise((resolve, reject) => {        setTimeout(() => {          console.timeEnd(`task ${t}`);          resolve();        }, t);      })    }      console.log('Create Promises');    const task1 = t1(100);    const task2 = t1(200);    const task3 = t1(10);      console.log('Await for each task');    const [r1, r2, r3] = [await task1, await task2, await task3];      console.log('Done');  }())

But as with Promise.all, the parallel promises need to be properly handled in case of an error. You can read more about that here.

Be careful not to confuse the previous code with the following:

let [r1, r2] = [await t1(100), await t2(200)]; 

function t1(t) {    console.time(`task ${t}`);    console.log(`start task ${t}`);    return new Promise((resolve, reject) => {      setTimeout(() => {        console.timeEnd(`task ${t}`);        resolve();      }, t);    })  }  console.log('Promise');  Promise.all([t1(100), t1(200), t1(10)]).then(async() => {      console.log('Await');    let [r1, r2, r3] = [await t1(100), await t1(200), await t1(10)]  });

Using these two methods is not equivalent. Read more about the difference.

In the end, Promise.all is a cleaner approach that scales better to an arbitrary number of tasks.

like image 110
lucascaro Avatar answered Oct 07 '22 11:10

lucascaro