JavaScript Async/Await - javascript

I'm trying to understand JavaScript async/await. How can I rewrite the below such that the output is "Hi" then "Bye" instead of "Bye" then "Hi":
JSFiddle
sayHi()
.then(sayBye);
async function sayHi() {
await setTimeout(function() {
$("#myOutput").text('hi');
}, 1000);
}
async function sayBye() {
$("#myOutput").text('bye');
}

In order to await setTimeout it needs to be wrapped into Promise. Then with async/await you can flatten your code write it without Promise then API:
(async () => { // await has to be inside async function, anonymous in this case
await sayHi()
sayBye()
})()
async function sayHi() {
return new Promise(function (resolve) {
$("#myOutput").text('hi');
setTimeout(function() {
resolve()
}, 1000)
});
}
async function sayBye() {
$("#myOutput").text('bye');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myOutput"></div>

setTimeout doesn't return a Promise. Create a helper function to wrap it in a Promise and then you can await it.
function delay(fn, t) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(fn());
}, t);
});
}
sayHi()
.then(sayBye);
async function sayHi() {
await delay(() => {
//$("#myOutput").text('hi');
console.log("Hi");
}, 1000);
}
async function sayBye() {
//$("#myOutput").text('bye');
console.log("Bye");
}

Use the Promise way
sayHi()
.then(sayBye);
function sayHi() {
return new Promise(resolve => {
setTimeout(()=> {
$("#myOutput").text('hi'), resolve()
}, 1000);
})
}
async function sayBye() {
$("#myOutput").text('bye');
}
or the sayHi like this:
async function sayHi() {
await new Promise(resolve => {
setTimeout(()=> {
$("#myOutput").text('hi'), resolve()
}, 1000)
})
}

Using async/await is an excellent way to build acynchronous code in a quite controllable way. Promise based async function goes into microtasks depository, which event loop executes before events and methods contained in ordinary DOM refresh/web API depository (setTimeout() for example). However some versions of Opera and Firefox browsers set priority to setTimeout() over microtasks depository. Anyway, you can control order of execution if you combine Promise based function with async/await enabled function. For example:
// create function that returns Promise
let hi = () => {
return new Promise((resolve, reject) => {
setTimeout(_ => {
resolve('Hi '); // after 1500ms function is resolved and returns 'Hi '
}, 1500);
});
}
// create ordinary function that will return 'bye'
let sayBye = () => {
return 'Bye';
}
// create third function that will be async 'enabled',
// so it can use await keyword before Promise based functions
let sayHi = async () => {
let first = await hi(); // we store 'Hi ' into 'first' variable
console.log(first);
let second = sayBye(); // this execution will await until hi() is finished
console.log(second);
}
// execute async enabled function
sayHi();
We can add try / catch block inside sayHi() function for controlling error on promise reject(), but this is out of scope of your question.
Have a nice day!

You cannot use async/await for functions that are not returning Promise
When an async function is called, it returns a Promise. When the async function returns a value, the Promise will be resolved with the returned value. When the async function throws an exception or some value, the Promise will be rejected with the thrown value.
An async function can contain an await expression, that pauses the execution of the async function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Usually it is used to handle data that comes from server, because when you have multiple queries it can override previous one and you will handle the wrong one.
Async/await lets you handle exactly data you are awaiting for.

Related

Async await issue on nodejs

I'm learning to use async/await and this is quite confused to me. As I know, async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
async function foo() {
setTimeout(() => {
throw new Error('error');
}, 5000);
}
async function test() {
try {
await foo();
} catch (err) {
console.log(err);
}
console.log('not reached');
}
test();
Expected output: log the error after 5 secs, then log "not reach".
What actually happened: "not reach" gets logged right after I start the script, then the error gets logged after 5 seconds.
Attempts: the following code does exactly what I want, but I don't know what's the difference between those code.
Environment: nodejs 16.14.2
function foo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('foo'));
}, 5000);
});
}
async function test() {
try {
await foo();
} catch (err) {
console.log(err);
}
console.log('not reached');
}
test();
Thanks a lot!
foo needs to actually resolve
Your example doesn't work because foo doesn't actually care about the timeout. It just starts the timeout then returns immediately. What you need to do is make foo resolve when the timeout fires, which actually requires you to construct a Promise explicitly.
async function foo() {
return new Promise(resolve => {
setTimeout(resolve, 5000)
})
}
Since you return a Promise, you could technically not declare foo as async, but it doesn't matter, and (I think) it's still helpful for other developers to see that the function returns a Promise without having to look through the implementation.
In your second example, foo returns a promise, setTimeout needs to produce a promise for it to work in your example.
For example
async function foo() {
// promise returned
return new Promise(resolve => {
setTimeout(() => { resolve() } , 5000)
})
}

If I use async/await, it doesn't run in order

I have a question about the async/await execution.
example codes
async firstMethod(){
new Promise((resolve, reject)) => {
setTimeout(() => {
resolve("test1");
}, 3000);
});
}
async secondMethod() {
new Promise((resolve, reject)) => {
setTimeout(() => {
resolve("test2");
}, 1000);
});
}
await firstMethod();
await secondMethod();
So, When the two methods are executed, the following results are obtained.
test2
test1
However, if a return is attached, the result value is as follows.
async firstMethod(){
return new Promise((resolve, reject)) => {
setTimeout(() => {
resolve("test1");
}, 3000);
});
}
async secondMethod() {
return new Promise((resolve, reject)) => {
setTimeout(() => {
resolve("test2");
}, 1000);
});
}
await firstMethod();
await secondMethod();
test1
test2
Why is that? I'd appreciate it if you could explain it.
In the first case you just await the outer promises (that are the firstMethod and secondMethod functions) and the inner promises created by new Promise do not get awaited, and simply run to completion in the background.
In the second case, because of promise unwrapping you await the returned inner promises together with the outer function promises.
The reason why in the first example those 2 functions do not run in order is because you are not waiting for anything. If you try to remove the async from the function definition in the first example you will get the same result because the function does not need the async because it does not require an await. What you could do to have the same result has the second example is by adding a await before the new Promise.
Note: You also do not need the async in the second example because you are not waiting for anything, you are just returning a Promise in which you wait outside the scope.

How to use async await in Nuxt.js?

Tried to make async/await work in Nuxt, but I don't know why it doesn't work anywhere.
In the created hook, it just doesn't wait for the setTimeout, and activates the second console.log(). In the methods, it does not recognize the this in addition to the setTimeout skipping it.
Can someone give me an example of how it should be spelled correctly for it to work? I'm using Nuxt.
<script>
export default {
data() {
return {
comprobante: true,
};
},
async created() {
await setTimeout(() => {
console.log("hola");
}, 1000);
console.log("adios");
},
methods: {
noSalir: async () => {
await setTimeout(() => {
console.log("hola");
}, 1000);
console.log("adios");
this.comprobante = !this.comprobante;
}
}
};
</script>
await only awaits a Promise or an async call (which resolves to a Promise). When you await anything other than a Promise, it returns immediately. Since setTimeout does not return a Promise (it returns a timer ID), the await call on that line returns immediately.
To make that await actually wait for the setTimeout to complete, wrap it in a Promise:
async function created() {
console.log('waiting...')
await new Promise(resolve => setTimeout(() => {
console.log('hola')
resolve()
}, 1000))
console.log('adios')
}
created()
Regarding the wrong this in your method, the problem is you've declared it as an arrow function, which captures the outer this (undefined in an SFC). To ensure the correct this context, use a regular function here:
export default {
methods: {
// noSalir: async () => {...} ❌ don't use arrow functions here
async noSalir() {...} ✅
}
}
demo

Simple async await question with function returns

I have a simple yet perplexing issue with async functions.
I wish to simply return the value when its ready from the function.
Here is a sample code:
async function test() {
setTimeout(function() {
return 'eeeee';
}, 5000);
}
test().then(x => {
console.log(x)
});
You will get undefined been logged at once.
It's clear that you are trying to write a sleep() async function, but do remember that setTimeout is a sync function calling with a callback function will be executed at a given time, so while you are executing test(), the calling will run to end and return undefined as you have no return statement in the function body, which will be passed to your .then() function.
The right way to do this is to return a Promise that will be resolved after a given time, that will continue the then call.
async function sleep(time){
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve("echo str")
},time)
})
}
sleep(5000).then((echo) => console.log(echo))
sleep function in short
const sleep = async time => new Promise(resolve=>setTimout(resolve,time))
With Promises
const setTimer = (duration) => {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Done!');
}, duration);
});
return promise;
};
setTimer(2000).then((res) => console.log(res));
An async function has to return a promise. So to fix this, you can wrap your setTimeout function in a new promise like so:
async function test(){
return await new Promise((resolve, reject) => {
setTimeout(function(){
resolve('eeeee');
},5000);
})
}
test().then(x => {
console.log(x)
});
You can learn more about async/await on the MDN docs here. Hope this helps!

About 'pending' and 'fulfilled' promise of javascript async function

async function pending() {
return new Promise((resolve, reject) => { resolve(1) });
}
async function fulfilled() {
return 1;
}
function promiseState(p) {
return Promise.race([ Promise.resolve(p).then(() => "fulfilled", () => "rejected"), Promise.resolve().then(() => "pending") ]);
}
promiseState(pending()).then(s => { console.log(s); }); // pending
promiseState(fulfilled()).then(s => { console.log(s); }); // fulfilled
pending().then(r => { console.log(r); }); // 1
fulfilled().then(r => { console.log(r); }); // 1
What's different?
When should I use 'return new Promise(...' in async function? and Why?
It's the same as the difference between
function pending() {
return Promise.resolve(Promise.resolve(1));
}
and
function fulfilled() {
return Promise.resolve(1);
}
The former just takes one promise tick longer to settle.
When should I use 'return new Promise(...' in async function?
Probably never. See How to turn this callback into a promise using async/await? and What is the benefit of prepending async to a function that returns a promise?.
You should not construct Promises explicitly inside another Promise or async function, thats the promise constructor antipattern. It just adds additional overhead and you get no benefit whatsoever. If you somewhen really need the Promise constructor (for wrapping a callback API), then the surounding function should not be async, just return the promise.

Categories