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.
Related
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...
const tryToGetResult = async () => {
const networkResult = await someNetworkRequest();
console.log(networkResult); //Make sure networkResult is resolved to an object
return networkResult;
}
const result = tryToGetResult();
networkResult is already an object and the flow has been taken care of by using async/await. But I don't understand why const result = tryToGetResult(), the result variable here is getting a promise instead?
I understand that the situation can be fixed by adding await as const result = await tryToGetResult();, I simply don't understand why the need of await here coz the flow of execution is clearly correct?
Functions marked as async always return a Promise
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
An asynchronous function is a function which operates asynchronously via the event loop, using an implicit Promise to return its result.
When i run console.log (f ()) i want it returns the data that came from getData (url), but it keeps returning Promise {<pending>}. I thought using await keyword would solve this by making the code execution stops untilgetData ()returns something. I know if i use f().then(console.log) it will work fine, but i just don't understand why console.log (f()) does not works too.
There is a way to achieve the same result f().then(console.log) but not using the then () function?
async function f() {
const url = `https://stackoverflow.com`;
let d = await getData(url);
return d;
}
console.log(f());
If it is impossible, can you explain why?
f is an async function, so it still returns a Promise.
To wait for this promise to resolve you need to await it.
(async () => console.log(await f())();
Or in long:
async function run(){
console.log(await f());
}
run();
async and await do not stop functions from being asynchronous.
An async function will always return a Promise. It just resolves to whatever you return instead of requiring that you call resolve function with the value.
Inside an async function, you can await other Promises. This simulates non-asynchronous code, but it is just syntax. It doesn't let you do anything you couldn't do with then(), it just gives you a simpler syntax.
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.
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.
Actually it depends on your node version, But if you can use async/await then your code will be more readable and easier to maintain.
When you define a function as 'async' then it returns a native Promise, and when you call it using await it executes Promise.then.
Note:
Put your await calls inside a try/catch, because if the Promise fails it issues 'catch' which you can handle inside the catch block.
try{
let res1 = await your-async-function(parameters);
let res2 = await your-promise-function(parameters);
await your-async-or-promise-function(parameters);
}
catch(ex){
// your error handler goes here
// error is caused by any of your called functions which fails its promise
// this methods breaks your call chain
}
also you can handle your 'catch' like this:
let result = await your-asyncFunction(parameters).catch((error)=>{//your error handler goes here});
this method mentioned does not produce an exception so the execution goes on.
I do not think there is any performance difference between async/await other than the native Promise module implementation.
I would suggest to use bluebird module instead of native promise built into node.
At this point the only reason to use Promises is to call multiple asynchronous jobs using Promise.all() Otherwise you’re usually better with async/await or Observables.
Its depending upon what approach you are good with, both promise and async/await are good, but if you want to write asynchronous code, using synchronous code structure you should use async/await approach.Like following example, a function return user with both Promise or async/await style.
if we use Promise:
function getFirstUser() {
return getUsers().then(function(users) {
return users[0].name;
}).catch(function(err) {
return {
name: 'default user'
};
});
}
if we use aysnc/await
async function getFirstUser() {
try {
let users = await getUsers();
return users[0].name;
} catch (err) {
return {
name: 'default user'
};
}
}
Here in promise approach we need a thenable structure to follow and in async/await approach we use 'await' to hold execution of asynchronous function.
you can checkout this link for more clarity Visit https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
Yesterday I made a tentative decision to switch from using Promises to using Async/Await, independent of nodejs, based on the difficulty in accessing previous values in the Promise chain. I did come up with a compact solution using 'bind' to save values inside the 'then' functions, but Async seemed much nicer (and it was) in allowing direct access to local variables and arguments. And the more obvious advantage of Async/Await is, of course, the elimination of the distracting explicit 'then' functions in favor of a linear notation that looks much like ordinary function calls.
However, my reading today uncovered problems with Async/Await, which derail my decision. I think I'll stick with Promises (possibly using a macro preprocessor to make the 'then' functions look simpler) until Async/Await gets fixed, a few years from now.
Here are the problems I found. I'd love to find out that I am wrong, that these have easy solutions.
Requires an outer try/catch or a final Promise.catch(), otherwise errors and exceptions are lost.
A final await requires either a Promise.then() or an extra outer async function.
Iteration can only be properly done with for/of, not with other iterators.
Await can only wait for only one Promise at a time, not parallel Promises like Promise chains with Promise.all.
Await doesn't support Promise.race(), should it be needed.
I am using async/await in several places in my code.
For example, if I have this function:
async function func(x) {
...
return y;
}
Then I always call it as follows:
async function func2(x) {
let y = await func(x);
...
}
I have noticed that in some cases, I can omit the await and the program will still run correctly, so I cannot quite figure out when I must use await and when I can drop it.
I have concluded that it is "legitimate" to drop the await only directly within a return statement.
For example:
async function func2(x) {
...
return func(x); // instead of return await func(x);
}
Is this conclusion correct, or else, what am I missing here?
EDIT:
A small (but important) notion that has not been mentioned in any of the answers below, which I have just encountered and realized:
It is NOT "legitimate" to drop the await within a return statement, if the called function may throw an exception, and that statement is therefore executed inside a try block.
For example, removing the await in the code below is "dangerous":
async function func1() {
try {
return await func2();
}
catch (error) {
return something_else;
}
}
The reason is that the try block completes without an exception, and the Promise object returns "normally". In any function which calls the outer function, however, when this Promise object is "executed", the actual error will occur and an exception will be thrown. This exception will be handled successfully in the outer function only if await is used. Otherwise, that responsibility goes up, where an additional try/catch clause will be required.
If func is an async function then calling it with and without await has different effects.
async function func(x) {
return x;
}
let y = await func(1); // 1
let z = func(1) // Promise (resolves to 1)
It is always legitimate to omit the await keyword, but means you will have to handle the promises in the traditional style instead (defeating the point of async/await in the first place).
func(1).then(z => /* use z here */)
If your return statements use await then you can be sure that if it throws an error it can be caught inside your function, rather than by the code that calls it.
await just lets you to treat promises as values, when used inside an async function.
On the other hand, async works quite the opposite, it tags the function to return a promise, even if it happens to return a real, synchronous value (which sounds quite strange for an async function... but happens often when you have a function that either return a value or a promise based on conditions).
So:
I have concluded that it is "legitimate" to drop the await only directly within a return statement.
In the last return statement of an async function, you just are returning a Promise, either you are return actually a directly a promise, a real value, or a Promise-as-value with the await keyword.
So, is pretty redundant to use await in the return statement: you're using await to cast the promise to a value -in the context of that async execution-, but then the async tag of the function will treat that value as a promise.
So yes, is always safe to drop await in the last return statement.
PS: actually, await expects any thenable, i.e. an object that has a then property: it doesn't need a fully spec compliant Promise to work, afaik.
PS2: of course, you can always drop await keyword when invoking synchronous functions: it isn't needed at all.
An async function always returns a Promise.
So please keep in mind that these writing of an async function are all the same:
// tedious, sometimes necessary
async function foo() {
return new Promise((resolve) => resolve(1)))
}
// shorter
async function foo() {
return Promise.resolve(1)
}
// very concise but calling `foo` still returns a promise
async function foo() {
return 1 // yes this is still a promise
}
You call all of them via foo().then(console.log) to print 1. Or you could call them from another async function via await foo(), yet it is not always necessary to await the promise right away.
As pointed out by other answers, await resolves the promise to the actual return value statement on success (or will throw an exception on fail), whereas without await you get back only a pending promise instance that either might succeed or fail in the future.
Another use case of omitting (i.e.: being careful about its usage) await is that you might most likely want to parallelize tasks when writing async code. await can hinder you here.
Compare these two examples within the scope of an async function:
async function func() {
const foo = await tediousLongProcess("foo") // wait until promise is resolved
const bar = await tediousLongProcess("bar") // wait until promise is resolved
return Promise.resolve([foo, bar]) // Now the Promise of `func` is marked as a success. Keep in mind that `Promise.resolve` is not necessary, `return [foo, bar]` suffices. And also keep in mind that an async function *always* returns a Promise.
}
with:
async function func() {
promises = [tediousLongProcess("foo"), tediousLongProcess("bar")]
return Promise.all(promises) // returns a promise on success you have its values in order
}
The first will take significantly longer than the last one, as each await as the name implies will stop the execution until you resolve the first promise, then the next one.
In the second example, the Promise.all the promises will be pending at the same time and resolve whatever order, the result will then be ordered once all the promises have been resolved.
(The Bluebird promise library also provides a nice Bluebird.map function where you can define the concurrency as Promise.all might cripple your system.)
I only use await when want to work on the actual values. If I want just a promise, there is no need to await its values, and in some cases it may actually harm your code's performance.
I got a good answer above, here is just another explanation which has occurred to me.
Suppose I have this:
async function func(x) {
...
return y;
}
async function func2(x) {
...
return await func(x);
}
async function func3(x) {
let y = await func2(x);
...
}
The reason why I can safely remove the await in the return statement on func2, is that I already have an await when I call func2 in func3.
So essentially, in func3 above I have something like await await func(x).
Of course, there is no harm in that, so it's probably better to keep the await in order to ensure desired operation.