I sort of understand what each is doing. setTimeout, "The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds." Async await, returns a promise, and is just a function that can be put in a queue and have the results of the function checked in later.
But both allow me to "delay code", they are both asynchronous functions. So when would you use one rather than the other one?
Thank you for any help!
They are completely different.
Using async/await allows you to consume Promises in a flat manner in your code, without nesting callbacks or hard-to-read .then chains. For example:
const doSomething = async () => {
await asyncStep1();
await asyncStep2();
await asyncStep3();
};
where each async step returns a Promise.
await only allows you to "delay" code in a block if you already have a Promise to work with (or something that you convert to a Promise).
setTimeout is not similar at all to async/await - setTimeout doesn't consume a Promise or have anything to do with Promises at all. setTimeout allows you to queue a callback to be called later, after the timeout time has finished.
Unlike await, setTimeout does not delay code in a block - rather, you pass it a callback, and the callback gets called later.
Cool question.
You're right that they're both asynchronous code.
As a simple answer to the difference. If you are doing something like:
const fetchUser = async () => {
const result = await fetch("/user");
return await result.json();
}
async main1() {
setTimeout(() => console.log("done", 2000));
}
async main2() {
await fetchUser();
console.log("done");
}
The setTimeout is always going to take ~2000ms before it logs "done", provided you haven't blocked the thread somewhere else. The fetchUser is going to log "done" when the API is complete, that might be 100ms, that might be 10000ms.
But the difference is a bit more involved than that:
It's partly to do with the difference in a callback style of code or a promise style of code.
The callback style is an older of coding, the difference here is a bit more than that.
Let's set aside setTimeout for a moment and talk about two ways you might make a fetch call.
const fetchUserOne = async() => {
const result = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const json = await result.json();
return json;
}
const fetchUserTwo = () => {
return fetch('https://jsonplaceholder.typicode.com/todos/2')
.then(response => response.json())
};
async function main() {
const result1 = fetchUserOne();
const result2 = fetchUserTwo();
console.log(result1);
console.log(result2)
const awaitedResult1 = await result1;
const awaitedResult2 = await result2;
console.log(awaitedResult1);
console.log(awaitedResult2);
}
main().then(console.log("complete"));
Now what I want to highlight here, is that although the second example uses a callback style - they are both using promises.
When you run the code (and press F12 to see the full object), you'll note that the log of result1 and result2 are promises.
Window.setTimeout on the other hand does not use a Promise.
const result = setTimeout(() => {
console.log("done");
}, 2000);
console.log(result);
The return value of the setTimeout is a number, which can be used to cancel the timeout.
And that brings us to the main difference:
Promises are not cancellable, setTimeout is
See this Stack Overflow question about cancelling a promise.
To show an example of this, let's modify our example above.
const fetchUser = async () => {
const result = await fetch("https://jsonplaceholder.typicode.com/todos/1");
return await result.json();
}
let timeout;
async function main1() {
console.log("start main1");
timeout = setTimeout(() => console.log("done timeout"), 2000);
}
async function main2() {
console.log("start main2");
await fetchUser();
console.log("done fetchuser");
}
main1();
main2();
clearTimeout(timeout);
Above, we can see that we can quite easily abort the timeout call, whereas we can't cancel a promise directly.
This is not to say that you can't cancel that fetch request, as you can see in this thread, but you can't cancel the promise itself.
Firstly, setTimeout is static timer that depends on the given time. On the other hand async await is something that is not static. It will wait until it awaited function or promise return any response or error
Secondly, You can Timeout any execution but you cannot await any function.
Here is the Official doc Async await
setTimeout allows you to delay execution for an approximate amount of time.
let log = () => console.log('log');
// invokes `log()` after a delay
setTimeout(log, 1000);
async/await helps you deal with promises without function handlers; it's just syntactic sugar. It doesn't actually delay execution.
let promise = Promise.resolve(5);
let main = async() => {
// without await
promise.then(value => console.log(value));
// with await
console.log(await promise);
};
main();
Both async await and setTimeout aren't similar eventhough it looks like they are but they aren't.
If you are new to JavaScript then, you can think of setTimeout as a timer, so whatever block of code or function is passed to setTimeout it will execute after a fixed time, it basically delays the execution of code, while on the other hand async await isn't bound to any timer, to understand simply, function or promise that uses async await will wait until the function or promise returns an appropriate response...
Related
async abc(){
await some().then(() => {
//do inside then
});
//other code
}
Does the "await" wait only on the some() or does it await the some() and its then() before going to //other code? Basically the question is does the await wait also on the then part to be done before moving to next statement.
some().then() returns a new promise and the await waits on that new promise so it will wait for the .then() handler and any promise that it might return before going on past the await. In other words, it waits for that entire promise chain.
In general, this is not great style to mix await and .then() in the same statement as you would typically want to stick with await instead of .then() as in:
async abc(){
let result = await some();
// do something with result
//other code
}
This gives you the simpler looking and more sequential code design that await enables.
You could also use arrow function to achieve this.
const some = () => 'something';
const abs = async () => {
const result_from_some = await some();
// do something with result_from_some
}
But please, if the value in 'result_from_some' may change, then is better to use let instead of const
Hope this helps someone.
This question already has answers here:
Why is the method executed immediately when I use setTimeout?
(8 answers)
How to turn this callback into a promise using async/await?
(2 answers)
Closed 3 years ago.
I already posted a question on this subject here on StackOverflow. Following the recommendations, I have tried to simplify my question.
I don't understand how to make synchronous code with Promises and their new polished version using async/await, despite the fact I have read and tried different approaches.
Here, I link some good documentation on the subject, in case it can help people in the future. Basically, Promises are an answer to callback hell and a way to make code execute after some other code has been executed, making things happening synchronously since JavaScript (hence Node.js) is asynchronous by nature. Async/await is built on top of Promises and simplify the code.
understanding JavaScript Promises
modern JavaScript with async/await
Async/await explained with examples
why moving from Promises to async/await
Despite I seem to understand the concept, I can't explain the results I obtain. To better my comprehension, here is a test file using node.js -v v8.10.0
/* This file try to use Promises and async/await to run code synchronously */
/* declaration of some Promisified functions */
const doSomethingAsync = () => { // direct declaration using new Promise and Promise.resolve()
return new Promise(resolve => { // This is just a promise, necesiry to wait for it
setTimeout(() => resolve('I want to be first'), 3000);
});
};
const test1 = async () => { // indirect Promise declaration usind async
return setTimeout(() => console.log("test1, I want to be executed first"), 3000); // async => the function returns a promise hence return a resolve,
}; // we should use await to wait for the Promise.resolve()
/* create intermediate calling functions making code synchronous to use console.log() properly */
const doSomething = async () => {
console.log( await doSomethingAsync());
};
const callTest = async () => {
console.log("hope to be executed before test1() resolve");
await test1();
console.log("hope to be executed after test1() resolve");
}
/* hope to run code synchronously in the following using .then() keyword */
console.log('1');
doSomething();
console.log('2');
callTest();
console.log('3');
doSomething()
.then(console.log("I want to be after"))
.catch(error =>{
console.log(error);
});
console.log('4');
console.log( doSomethingAsync().then(console.log("I want to be after too")) );
console.log('5');
// hope to run code synchronously in the following using await keyword
(async () => {
let test2 = await doSomethingAsync();
let test3 = await doSomething();
await test1();
console.log(`value doSomethingAsync: ${test2}`);
console.log(`value doSomething: ${test3}`);
})();
console.log('6');
What I expect is to see the code putted into the .then() keyword to be executed synchronously after Promise.resolve() fire... but it's not what I observe. See below the output of the program in my terminal:
ʘ node test_promises.js
1
2
hope to be executed before test1() resolve
3
I want to be after
4
I want to be after too
Promise { <pending> }
5
6
hope to be executed after test1() resolve
test1, I want to be executed first
I want to be first
I want to be first
I want to be first
value doSomethingAsync: I want to be first
value doSomething: undefined
test1, I want to be executed first
From the output, it is clear that .then() runs before the code inside the called function.
from StackOverflow
The success or the error handler in the then function will be called only once, after the asynchronous task finishes.
It seems not to be the case. Hence my question is straightforward:
Question: Why is .then() called before the asynchronous tack finish, and how to properly code with Promises, .then() and async/await (which is supposed to replace then)?
EDIT
From the answer of the community, I understand that .then() fires directly when the values passed to it are not callback functions. Hence, by modifying the .then() like so .then(function() {console.log("I want to be after")} )
Ok, I had not understood. I get
ʘ node test_promises.js
1
2
hope to be executed before test1() resolve
3
4
Promise { <pending> }
5
6
hope to be executed after test1() resolve
test1, I want to be executed first
I want to be after too
I want to be first
I want to be first
I want to be after
I want to be first
value doSomethingAsync: I want to be first
value doSomething: undefined
test1, I want to be executed first
I still do not understand why the console.log()s fire before the await function call in
const callTest = async () => {
console.log("hope to be executed before test1() resolve");
await test1();
console.log("hope to be executed after test1() resolve");
}
Thanks for the patience of the community
EDIT 2
From the answers of the community:
An async function only waits for the things that are awaited inside
its code. It does not automagically recognise any calls that do
something asynchronous. You need to explicitly promisify setTimeout
to make it work with promises. – Bergi ANSWER 2: return setTimeout(()
=> console.log("test1, I want to be executed first"), 3000) isn’t correct, because setTimeout doesn’t return a promise. Converting
functions that use callbacks, like setTimeout, without using other
helper functions is a little wordy: return new Promise(resolve => {
setTimeout(resolve, 3000); }); – Ry-♦
This means the correct code is the following:
// declaration of some Promisified functions
const doSomethingAsync = () => {
return new Promise(resolve => {
setTimeout(() => resolve('I want to be first'), 3000);
});
};
const test1 = async () => { // IMPORTANT CORRECTION: use Promise constructor
return new Promise(resolve => { setTimeout( () => {resolve("test1, I want to be executed first")}, 3000); }); // actuallu async do not transform the return
}; // function into a Promise
// create intermediate calling functions making code synchronous to use console.log() properly
const doSomething = async () => {
console.log( await doSomethingAsync());
};
const callTest = async () => {
console.log("hope to be executed before test1() resolve");
const resultTest1 = await test1(); // IMPORTANT CORRECTION: declare a variable to return the value of the executed function when exec is over, using await
console.log(resultTest1);
console.log("hope to be executed after test1() resolve");
}
// hope to run code synchronously in the following using .then() keyword
console.log('1');
doSomething();
console.log('2');
callTest();
console.log('3');
doSomething()
.then(function() {console.log("I want to be after")} ) // IMPORTANT CORRECTION: declare a callback function instead of executing the function
.catch(error =>{
console.log(error);
});
console.log('4');
console.log( doSomethingAsync().then(function() {console.log("I want to be after too")}) );
console.log('5');
// hope to run code synchronously in the following using await keyword, THIS IS THE "RIGHT" WAY TO USE ASYNC/AWAIT
(async () => {
let test2 = await doSomethingAsync();
let test3 = await doSomething();
await test1(); // this is the last await, it will be the last executed code
console.log(`value doSomethingAsync: ${test2}`);
console.log(`value doSomething: ${test3}`);
})();
console.log('6');
A special thank to everyone that helped. I hope this will be useful.
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.
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.
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).");
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.
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:
running
make promise 1
promise
make promise 2
promise
exiting right away!
What i want to run after the promise is resolved hello promise 1
What i want to run after the promise is resolved via await hello promise 2
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.
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.
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
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:
only use await when not handling error return
if no crucial need for error handling use await instead
use .then .catch if returned error message or data is crucial for debugging / or proper error handling instead of try catch for await
Choose any prefer method from code sample below
const getData = (params = {name: 'john', email: 'ex#gmail.com'}) => {
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);
});
}
This question is theoretical - I have no concrete problem to solve.
With that said, why does the async keyword wrap the return value of an async function in a promise? What's the point? Is it ONLY because the await expression expects a promise? Or is there some meaning / use behind this decision?
I thought i'd answer this primarily because async in Javascript used to confuse the hell out of me, and all of a sudden it snapped, so i hope this analogy may help this happen for you.
You have an async event. This could be anything, getting something from a server, doing something in the browser that takes time, training a machine learning model (!), executing a function or method that uses a setTimeout etc.
The beauty of Javascript and a key reason it works so well for the browser is that it uses the processor thread it runs on in a very clever way that stops the thread from getting blocked by processes that take time (like the ones mentioned above)
Many other languages, for example Ruby run on more than one thread. It is possible to use service workers to run processes on multiple threads in javascript but that is outside the scope of this answer!
The async nature of the JS event loop allows the thread to 'go off' and do something else while it is waiting for a process to finish.
The problem with this from a programming point of view is that it is possible for something in the code that relies on the result of a blocking event to get 'undefined' as a result of the event if it doesn't wait for the event to finish before it tries to use the result of it. Take this piece of code below
let scopedVariable
console.log('the code has started')
setTimeout(() => {
scopedVariable="I am the result of some async process"
}, 5000);
console.log(scopedVariable)
When the code reaches the console log, the setTimeout hasn't yet completed. As the setTimeout sets the scopedVariable only when it completes, the variable is undefined when we log it
if however
We wrap the timeout in a promise we can await it's resolve callback (first argument of promise) and the code will 'pause' until the promise reaches the resolve callback before continuing.
When we await the promise and the setTimeout completes, the resolve function sets the variable, so that when we console log it it holds the value from the promise
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
const result = await asyncEvent
console.log(scopedVariable)
}
container()
You can use await and .then interchangably
For example we could go:
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
asyncEvent.then(() => console.log(scopedVariable))
}
container()
once again the code will pause at .then and then continue when the asyncEvent promise has resolved.
In fact if we use .then we don't need to enclose it in an async function so we can rewrite it like this
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
asyncEvent.then(() => console.log(scopedVariable))
The great thing about .then is that the accompanying .catch allows you to catch any errors thrown by the async event (for example if retrieving something from a server when there is an error). For async await you need to wrap potentially dangerous functions in a try catch.
In order to use await you need to be inside an async function (hence the async container function above). This is not necessary with .then, but .then and .catch chains can make your code messy.
I hope this helps!
The async and await operators are just syntactic sugar that hide the underlying use of promises to implement asynchronous code.
Using async before a function definition makes the function return a promise that resolves to the function's return value, rather than returning normally.
Using await before an asynchronous function call suspends the current function until the promise that it returns is resolved. It's basically equivalent to wrapping the remainder of the function in an anonymous function, and using that as the .then() callback of the promise.
For more information between the relationship, see How to translate Promise code to async await
I have two asynchronous methods that return values, one of which is needed immediately and the other might be in use, based on the first result. However, I don't want to wait for the first result to come in before kicking off the second method and create an execution sequence dependency.
Using ES7 syntax, I would assume that await-ing a Promise would be the same as await-ing a function that returns a Promise, but it doesn't work:
async function tester() {
async function foo() { await setTimeout(() => {}, 2000)}
async function bar() { await setTimeout(() => {}, 1000)}
let rcFoo = foo();
let rcBar = await bar();
if (true) { // Some conditional based on rcBar
await rcFoo;
console.log(rcFoo); // It's a Promise object
}
}
Two questions:
Am I even understanding the asynchronous nature of Javascript correctly? If the above code would have worked, would it have achieved my goal of running two asynchronous functions concurrently-ish, or is it just not possible to do it?
Is it possible to somehow await an object that is a Promise like I tried, or does it have to reference a function directly?
Thanks..
In your code, foo will start right away, and then bar will start. Even if foo finished first, your code still awaits for the bar promise to finish before proceeding.
You can await everything as long as it's a promise, whether it's a variable or a returned value from a function call. As far as I know (I might be wrong), setTimeout doesn't return a promise, but it would be easy to convert it to one:
async function foo() {
return new Promise(resolve => setTimeout(resolve, 2000))
}
async function bar() {
return new Promise(resolve => setTimeout(resolve, 1000))
}
I would assume that await-ing a Promise would be the same as await-ing a function that returns a Promise
The same as awaiting the result of a call to a function that returns a promise, yes (which is awaiting a promise).
but it doesn't work:
await rcFoo;
console.log(rcFoo); // It's a Promise object
It does work, only awaiting a variable doesn't change that variable. You can only await values, and the result of the promise will become the result value of the await expression:
let res = await promise;
console.log(res); // a value
console.log(promise) // a promise for the value
That said, setTimeout doesn't return a promise, so your code doesn't sleep three seconds. You will have to promisify it, like e.g. #PedroMSilva showed it.