Reputation: 1557
I have a simple code in JavaScript that execute a request in an API and return the response, simple. But in this case I will have thousands of requests. So, which one of the code options will perform better, and why. Also which one is recommended as good pratices these days?
First options is using the .then to resolve the promises and the seccond one is using async / await.
In my tests the two options had very similar results without significant differences, but I'm not sure in scale.
// Using then
doSomething(payload) {
const url = 'https://link-here/consultas';
return this.axios.get(url, {
params: {
token: payload.token,
chave: payload.chave,
},
}).then(resp => resp.data);
}
// Using Async / await
async doSomething(payload) {
const url = 'https://link-here/consultas';
const resp = await this.axios.get(url, {
params: {
token: payload.token,
chave: payload.chave,
},
});
return resp.data;
}
Any explanation will be of great value.
Upvotes: 141
Views: 131274
Reputation: 7
Just to correct what @gabriel.hayes said:
.then()
is not recursive. Each step is independent of the next, with only the resolved value being passed along, thus once a .then()
step completes, its memory can usually be released unless it holds references.
In contrast, recursion involves a function calling itself (or another function in a recursive chain). Each step in a recursive process remains unresolved until all subsequent steps resolve. For example, if Func(n)
calls Func(n+1)
, it cannot finish until Func(n+1)
resolves, which in turn depends on Func(n+2)
, and so on. This creates a stack of unresolved calls that stays in memory until the recursion fully unwinds.
You can think of .then()
as passing a message along a chain: once the message is passed, you're done. In recursion, each step requests something from the next and must wait for a response, leaving it unresolved until the response arrives.
An analogy for this could be a restaurant:
.then()
: You tell the waiter to give the chef your best regards,So no, every part of the .then()
chain is not retained in memory until the final step resolves.
If you want a more in-depth look at how it works under the hood, this video does a great job of visualizing it.
And as we just entered 2025, I'm wishing you all a Happy New Year! 🎉
Upvotes: -2
Reputation: 39
Since in the code snippet no instructions are needed to get executed which is independent from promise, so in this case both async/await and then() works fine.
The difference between then() and async/await is that when a promise needs to get resolved in a function having then(), the function containing then() doesn't gets suspended from the call stack. It remains in the call stack till the promise gets resolved.
Whereas, in the async/await, when the resolve() keyword is encountered, the async function is suspended from the call stack, and the thread remains inactive if the async function is the entry point of the event handler. Only when the promise resolves, the async function gets pushed again in the call stack.
import React from "react";
import "./style.css";
import {useState, useEffect} from 'react'
export default function App(){
function doSomething(){
return new Promise((resolve)=>{
console.log('I am executing Promise')
resolve();
})
}
function handleClick1(){
doSomething().then(()=>{
console.log('I execute after then')
})
console.log('I am outside then')
}
async function handleClick2(){
await doSomething();
console.log('I execute after await')
}
return(
<>
<button onClick={handleClick1}>For THEN</button><br/>
<button onClick={handleClick2}>For AWAIT</button>
</>
)
}
So, if we need to perform other activities which is independent of promise resolution, we can use then() or we can use async/await but not as entry point, but a call from a calling function.
import React from "react";
import "./style.css";
import {useState, useEffect} from 'react'
export default function App(){
function doSomething(){
return new Promise((resolve)=>{
console.log('I am executing Promise')
resolve();
})
}
function handleClick1(){
doSomething().then(()=>{
console.log('I execute after then')
})
console.log('I am independent from promise resolution')
}
async function handleClick2(){
await doSomething();
console.log('I execute after await')
}
function callingFunction(){
handleClick2()
console.log('I am independent from promise resolution')
}
return(
<>
<button onClick={handleClick1}>For THEN</button><br/>
<button onClick={callingFunction}>For AWAIT</button>
</>
)
}
Upvotes: 0
Reputation: 91
Using .then() you will not get synchronous flavour that async/await can provide you.
A good article is here on this: https://masudsaiful.github.io/javascript-async-await-step-by-step-tutorial/#e-javascript-callback-function
Upvotes: 0
Reputation: 707158
From a performance point of view, await
is just an internal version of .then()
(doing basically the same thing). The reason to choose one over the other doesn't really have to do with performance, but has to do with desired coding style or coding convenience. Certainly, the interpreter has a few more opportunities to optimize things internally with await
, but its unlikely that should be how you decide which to use. If all else was equal, I would choose await
for the reason cited above. But, I'd first choose which made the code simpler to write and understand and maintain and test.
Used properly, await
can often save you a bunch of lines of code making your code simpler to read, test and maintain. That's why it was invented.
There's no meaningful difference between the two versions of your code. Both achieve the same result when the axios call is successful or has an error.
Where await
could make more of a convenience difference is if you had multiple successive asynchronous calls that needed to be serialized. Then, rather than bracketing them each inside a .then()
handler to chain them properly, you could just use await
and have simpler looking code.
A common mistake with both await
and .then()
is to forget proper error handling. If your error handling desire in this function is to just return the rejected promise, then both of your versions do that identically. But, if you have multiple async calls in a row and you want to do anything more complex than just returning the first rejection, then the error handling techniques for await
and .then()
/.catch()
are quite different and which seems simpler will depend upon the situation.
Upvotes: 222
Reputation: 41
As far as I understand .then() and await are not the same thing. An async function won't proceed with the next command until the promise is resolved/rejected since it's basically an implementation of generators. On the contrast, in the case of .then(), the execution of the function will proceed with the next command and the resolve/reject callback will be executed "when there's time" aka when the current event loop (not entirely sure about that part) will be completed.
tldr; on a single promise await and .then() behave similarly but when one promise needs another one to be resolved first then the two of them behave entirely different
Upvotes: 4
Reputation: 225
Many answer have been provided to this question already. However, to point out key information in the answers above and from my understanding, note below point:
Choose any prefer method from code sample below
const getData = (params = {name: 'john', email: '[email protected]'}) => {
return axios.post(url, params);
}
// anywhere you want to get the return data
// using await
const setData = async () => {
const data = await getData();
}
// to handle error with await
const setData = async () => {
try {
const data = await getData();
}
catch(err) {
console.log(err.message);
}
}
// using .then .catch
const setData = () => {
var data;
getData().then((res) => {
data = res.data; console.log(data)
}).catch((err) => {
console.log(err.message);
});
}
Upvotes: 1
Reputation: 540
If we just consider performance(time taken) then it actually depends on whether your operations are serial or parallel. If your tasks are serial then there will be no difference between await and .then. But if your tasks are parallel then .then will take less time. Consider the following example
let time = Date.now();
// first task takes 1.5 secs
async function firstTask () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
},1500)
})
}
// second task takes 2 secs
async function secondTask () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
},2000)
})
}
// using await
async function call(){
const d1 = await firstTask();
const d2 = await secondTask();
console.log(Date.now()-time, d1+d2)
}
call()
// using .then
async function call2(){
let d1=null,d2=null;
firstTask().then(data => {
d1=data;
if(d2){
console.log(Date.now()-time, d1+d2);
}
})
secondTask().then(data => {
d2=data;
if(d1){
console.log(Date.now()-time, d1+d2);
}
})
}
call2()
Here are the two tasks, first takes 1.5 secs and second takes 2 secs. Call function uses await where as call2 function uses .then . The output is as follows
From call2 2012 3
From call 3506 3
I hope it helps.
Upvotes: 5
Reputation: 139
For those saying await blocks the code until the async call returns you are missing the point. "await" is syntactic sugar for a promise.then(). It is effectively wrapping the rest of your function in the then block of a promise it is creating for you. There is no real "blocking" or "waiting".
run();
async function run() {
console.log('running');
makePromises();
console.log('exiting right away!');
}
async function makePromises() {
console.log('make promise 1');
const myPromise = promiseMe(1)
.then(msg => {
console.log(`What i want to run after the promise is resolved ${msg}`)
})
console.log('make promise 2')
const msg = await promiseMe(2);
console.log(`What i want to run after the promise is resolved via await ${msg}`)
}
function promiseMe(num: number): Promise<string> {
return new Promise((resolve, reject) => {
console.log(`promise`)
resolve(`hello promise ${num}`);
})
}
The await line in makePromises does not block anything and the output is:
Upvotes: 13
Reputation: 7078
As more explanation to @user280209 answer let's consider the following function which returns promise and compare its execution with .then()
and async await
.
function call(timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`This call took ${timeout} seconds`);
resolve(true);
}, timeout * 1000);
});
}
With .then()
(async () => {
call(5).then((r) => {
console.log(r);
});
await call(2); //This will print result first
await call(1);
})();
When running the above call the logs will be
This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true
As we can see .then()
didn't pause the execution of its below line until it completes.
With async/wait
(async () => {
await call(5); //This will print result first
await call(2);
await call(1);
})();
When run the above function logs will be
This call took 5 seconds
This call took 2 seconds
This call took 1 seconds
So I think if your promise's result won't be used in the following lines, .then()
may be better.
Upvotes: 51
Reputation: 857
There should be some corrections in this thread. await
and .then
are going to give very different results, and should be used for different reasons.
await
will WAIT for something, and then continue to the next line. It's also the simpler of the two because it behaves mechanically more like synchronous behavior. You do step #1, wait, and then continue.
console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");
.then
splits off from the original call and starts operating within its own scope, and will update at a time the original scope cannot predict. If we can put semantics aside for a moment, it's "more asynchronous," because it leaves the old scope and branches off into a new one.
console.log("Runs first.");
SomeFunction().then((value) => {console.log("Runs last (probably). Didn't use await on SomeFunction().")})
console.log("Runs second (probably).");
Upvotes: 66
Reputation: 97
Actually. Await/Async can perform more efficiently as Promise.then() loses the scope in which it was called after execution, you are attaching a callback to the callback stack.
What it causes is: The system now has to store a reference to where the .then() was called. In case of error it has to correctly point to where the error happens, otherwise, without the scope (as the system resumed execution after called the Promise, waiting to comeback to the .then() later) it isn't able to point to where the error happened.
Async/Await you suspend the exection of the method where it is being called thus preserving reference.
Upvotes: 8