Trying to understand async await - javascript

I'm trying to understand why this piece of code doesn't behave as I expect:
async function test() {
await setTimeout(() => {
console.log('done')
}, 1000)
console.log('it finished');
}
test();
This first prints it finished and then prints done afterwards. Shouldn't this code wait for the timeout to finish before executing console.log('it finished'); or have I misunderstood something?

You can only usefully await a promise.
setTimeout returns a timeout id (a number) that you can pass to clearTimeout to cancel it. It doesn't return a promise.
You could wrap setTimeout in a promiseā€¦
async function test() {
await new Promise( resolve => setTimeout(() => {
console.log('done');
resolve("done");
}, 1000));
console.log('it finished');
}
test();

Related

I am finding it hard to understand why the code after await does not execute

async function setTime() {
await new Promise(resolve => setTimeout(()=>{console.log("my func is fine")}, 5000));
}
async function realFunction() {
await setTime();
console.log("second call!");
}
In the above code, when i call realFunction, it logs my func is fine, but it does not log second call. Can someone help me understand what am I doing wrong, and how can I get the statement to be logged?
Because you never resolver your promise. You always need to resolve or reject it.
Also async / await is pretty much useless for setTime
function setTime(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
async function realFunction() {
await setTime(5000);
console.log("second call!");
}
The prolbem is that you never resolve the Promise so it's pending forever.
Try to change it like this:
async function setTime() {
await new Promise((resolve) =>
setTimeout(() => {
console.log('my func is fine');
resolve();
}, 5000)
);
}
async function realFunction() {
await setTime();
console.log('second call!');
}
You need to resolve the promise, and for that you can call resolve()
So your setTime() function would look like this:
async function setTime() {
await new Promise(resolve => setTimeout(()=>{
console.log("my func is fine")
return resolve();
}, 5000));
}

Why await is not waiting

How to wait for setTimeout to complete first
function a() {
setTimeout(() => {
console.log('should wait');
}, 5000);
}
async function b(c) {
console.log('hello');
await c();
}
b(a);
console.log('out');
My expected output is
Hello
should wait
out
setTimeout does not return a Promise and await only works with Promises.
Also, put the console.log("out") inside the b function for it to run after the a function.
Check the code snippet below, it does what you were looking for.
function a() {
return new Promise((res, rej) => {
setTimeout(() => {
console.log('should wait');
res();
}, 5000);
})
}
async function b(c) {
console.log('hello');
await c();
console.log('out');
}
b(a);
A function must return a promise if you want example to work properly (await keywords "awaits" for returned promise to resolve): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
You example should look like:
function a() {
return new Promise(resolve => {
setTimeout(resolve, 5000);
});
}
async function b(c) {
console.log('hello');
await c();
console.log('should wait');
}
await b(a);
console.log('out');
Note that you can use await keyword on function, because declaring function as async automatically makes it return a promise.

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!

Async/Await doesn't work in my example

Many JavaScript developers know about async/await and benefits of them so I try to test a old example of asynchronous action, let's see my experiment:
Undoubtedly the answer of below code is:
/*Line: 1*/ console.log(`1`);
/*Line: 2*/ console.log(`2`);
/*Line: 3*/ console.log(`3`);
//==> 123
So I wanna put a setTimeout for second line:
/*Line: 1*/ console.log(`1`);
/*Line: 2*/ setTimeout(() => {
console.log(`2`);
}, 0);
/*Line: 3*/ console.log(`3`);
//==> 132
Because of asynchronous action of second line the 2 is after the 13, so in the console 132 is showed.
I decide to use async/await feature of new JavaScript to see 123 again, so I wrote the above code like this:
(async () => {
console.log(`1`);
await setTimeout(() => {
console.log(`2`);
}, 0);
console.log(`3`);
})();
But it doesn't work and I saw 132 again in my console. Which part I did wrong or I don't know about it?
await waits for promise to be resolved. Since setTimeout is not a promise, execution of program will not wait till it is executed. You would need to wrap setTimeout() within promise as specified in first example of following link for your example to work as expected:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
setTimeout is not returning a promise. In order to get it to work, you will have to create a function returning a promise that is resolved inside the setTimeout callback.
(async () => {
console.log(`1`);
await new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
console.log(`2`);
},0);
});
console.log(`3`);
})();
You can only await a function which returns a promise. Note that await can only be used inside an async function:
async function someFunc() {
console.log(`1`);
await new Promise((resolve, reject) => setTimeout(() => {
console.log(`2`);
resolve();
}, 0));
console.log(`3`);
}
someFunc();
Await should be called on a function that returns a promise (otherwise it just returns).
setTimeout does not return a promise so you should wrap it with a function that returns a promise.
Read more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
This code should do the work.
(async() => {
console.log(`1`);
await (() => {
return new Promise( resolve => {
setTimeout(() => {
console.log(2);
resolve()
}, 1000);
});
})();
console.log(`3`);
})();
You need to create function, for example async function foo() {}, and make await calls inside it.

Understanding Promise and Await

I am just trying to understand how Promises and Async-Await work.
I want this to resolve by logging 1, 2, 3 in that order. Currently it logs 1, 3, 2.
I know the Promise doesn't really make sense here but in my program it has other uses so that needs to stay. The route from Caller function to Test also needs to stay (If need be you can change these but just know that they are there for a reason)
My question is how do I wait for the Caller function to resolve?
Here is my code:
function Test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
function Caller() {
Test();
}
console.log('1');
Caller();
console.log('3');
I have tried what I understand, which is to make the Caller() function await the Test Promise, but that of course makes the Caller() function async and therefore we still get 1, 3, 2
async function Caller() {
await Test();
}
Is there maybe some way to use await without making the function async?
You can only await a function that returns a promise (well, not quite true, if it doesn't return a promise it creates a promise that resolves instantly)
You can only await when you are inside an asynchronous function
function test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
async function caller() {
console.log('1');
await test();
console.log('3 (this is blocked awaiting the promise');
}
caller()
console.log("This is not blocked because caller is async");
This is a very straightforward, simple way of doing what you ask.
The await keyword can only be used inside functions
defined with async.
function test(ms) {
return new Promise((resolve, reject) => setTimeout(resolve, ms))
}
async function caller() {
console.log(1, ' - caller() started');
await test(2000).then(() => {
console.log(2, ' - test() resolved')
});
console.log(3, ' - delayed until "test()" has resolved');
return 4;
}
// wait for "caller()" to resolve
caller().then((result) => {
console.log(result, " - caller() finished")
});
console.log(5);
Here's a good article by Google which expands on the subject:
Async functions - making promises friendly.
Cite source.
here is how you could use functions like this:
function sleep(ms) {
return new Promise(r => {
setTimeout(() => r(), ms);
});
}
(async () => {
console.log(1);
await sleep(1000); // 1s
console.log(2);
await sleep(2000) // 2s
console.log(3)
})();
The previous answers are all correct but I just feel like this answer makes more sense. It is more accurate to the original question's code:
function Test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve();
}, 2000);
})
}
function Caller() {
return Test();
}
(async() => {
console.log('1');
await Caller();
console.log('3');
})();

Categories