Let us suppose that we've got a function that resolves a promise like below:
function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("done");
}, interval);
});
};
and let us suppose that we call that function inside an asynchronous function in two different ways;
slow synchornous way:
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
Here we simply await all three timeoutPromise() calls directly. Each subsequent one is forced to wait until the last one finished, this will result in total run time of around 9 seconds.
and fast asynchronous way:
async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000);
const timeoutPromise2 = timeoutPromise(3000);
const timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}
Here we store the three Promise objects in variables, which has the effect of setting off their associated processes all running simultaneously. This will result in total run time of around 3 seconds.
But the question is, why storing Promise objects in variables has the effect setting off their associated processs running simultaneously? what happens under the hood?
await foo();
await bar();
will only call bar (and thus create the second promise) after the promise returned by foo is resolved.
var x = foo();
var y = bar();
await x;
calls bar (and thus creating the second promise) before the promise returned by foo is resolved.
That's what makes the promises "concurrent". If you add console.log in various places you will see the difference in execution:
function timeoutPromise(name, interval) {
return new Promise((resolve, reject) => {
console.log(`Promise ${name} created.`);
setTimeout(function(){
console.log(`Promise ${name} resolved.`);
resolve("done");
}, interval);
});
};
async function timeTest1() {
console.log('test 1');
await timeoutPromise(1, 3000);
console.log('between promise 1 and 2');
await timeoutPromise(2, 3000);
}
async function timeTest2() {
console.log('test 2');
const timeoutPromise1 = timeoutPromise(1, 3000);
console.log('between promise 1 and 2');
const timeoutPromise2 = timeoutPromise(2, 3000);
await timeoutPromise1;
console.log('between promise 1 and 2 with await');
await timeoutPromise2;
}
timeTest1().then(timeTest2);
Related
My code should wait for 4-4 seconds for both the promise to execute total 8 seconds, but it is finishing in 4 seconds only. Why?
Where I am thinking wrong?
// a promise
let promise1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved1')}, 4000);
});
let promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved2')}, 4000);
});
// async function
async function asyncFunc() {
// wait until the promise resolves
let result1 = await promise1;
let result2 = await promise2;
console.log(result1);
console.log(result2);
}
// calling the async function
asyncFunc();
//expected output
**//wait for 4 seconds first**
Promise resolved1
**//wait for more 4 seconds**
Promise resolved2
//output
//waits for 4 seconds
Promise resolved1
Promise resolved2
new Promise(executor)
executor, A function to be executed by the constructor. It receives two functions as parameters: resolutionFunc and rejectionFunc. Any errors thrown in the executor will cause the promise to be rejected, and the return value will be neglected. The semantics of executor are detailed below.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise
// a promise
let promise1 = () => new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved1')}, 4000);
});
let promise2 = () => new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved2')}, 4000);
});
// async function
async function asyncFunc() {
// wait until the promise resolves
let result1 = await promise1();
console.log(result1);
let result2 = await promise2();
console.log(result2);
}
// calling the async function
asyncFunc();
The promise 1 & 2 is already running when you declared. If you want result that you expect, you should code as above.
When using async/await, your asynchronous code with begin executing, but its resolution will jump back into the synchronous code only when you use the await keyword. When you have multiple asynchronous functions, they will only execute sequentially when you have synchronous code running in between them because when you invoke the function is when the asynchronous portion of the code begins executing. In this case, the timer starts when you invoke the function, so you need to wait for the first timer to resolve before kicking off the second timer.
See this code snippet and check out the examples in this link to clarify.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
async function sequentialStart() {
console.log('==SEQUENTIAL START==')
// 1. Execution gets here almost instantly
const slow = await resolveAfter2Seconds()
console.log(slow) // 2. this runs 2 seconds after 1.
const fast = await resolveAfter1Second()
console.log(fast) // 3. this runs 3 seconds after 1.
}
The other issue is that when you declare your functions, you run them immediately and assign their values to variables. With minimum modification to your code, you need to set up your functions like below and only call them once you're ready to start the timer.
// a promise
let promise1 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved1');
}, 4000);
});
};
let promise2 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Promise resolved2');
}, 4000);
});
};
// async function
async function asyncFunc() {
// wait until the promise resolves
let result1 = await promise1();
console.log(result1);
let result2 = await promise2();
console.log(result2);
}
// calling the async function
asyncFunc();
Simple defenation of assync await
when yo declare async a function. The function will decleared as asyncronasly the default value of function is syncronasly . asyncronas function run block level(line by line) when you add await on a promise(function that return value) because of await compiler firstly resolved the promise and then run to next line of code
This might seem a silly question, but I am a newbie in this topic. In the script below i have two promises. By now "secondPromise" executing first, and then executing "firstPromise". Cuz in the "secondPromise" i set less time. But how to execute "firstPromise" first, after finished that, start executing the "secondPromise"?
How to rewrite the script below
(async function()
{
//var final = new Array();
var final;
const firstPromise = new Promise(
function(resolve)
{
let result = 2 + 2;
resolve(result);
setTimeout(() => console.log("please show me first"), 2000);
});
const secondPromise = new Promise(
function(resolve)
{
let result2 = 0;
resolve(result2 + 1);
setTimeout(() => console.log("please show me second"), 1000);
});
var myP = Promise.all([firstPromise, secondPromise]).then((values) => {
return values[0]+values[1];
});
return myP;
})();
(async function()
{
//var final = new Array();
var final;
const firstPromise = new Promise(
function(resolve)
{
let result = 2 + 2;
resolve(result);
setTimeout(() => console.log("please show me first"), 2000);
});
const secondPromise = new Promise(
function(resolve)
{
let result2 = 0;
resolve(result2 + 1);
setTimeout(() => console.log("please show me second"), 1000);
});
var myP = Promise.all([firstPromise, secondPromise]).then((values) => {
return values[0]+values[1];
});
return myP;
})();
Quentin's answer is correct: the function you pass to new Promise happens immediately. However: because you already have this in an async function, you can await Promises within it. This pauses the async function until the Promise resolves, so unlike your function with Promise.all that waits for your explicit new Promise Promises in parallel, my function waits for those Promises serially.
Furthermore, if you want the new Promise constructions you wrote to wait for the action in setTimeout, you need to wait and call the resolve method within the callback that setTimeout calls, not outside them as you have it.
console.log("start");
(async function () {
const firstValue = await new Promise(
// ^^^^^
function (resolve) {
let result = 2 + 2;
setTimeout(() => {
console.log("please show me first");
resolve(result); // Promise resolves after 2000ms
}, 2000);
});
const secondValue = await new Promise(
// ^^^^^
function (resolve) {
let result2 = 0;
setTimeout(() => {
console.log("please show me second");
resolve(result2 + 1);
}, 1000);
});
// These are values, not promises, because you await them.
// However, the async function still returns a Promise, because
// "async" covers the asynchronicity of the Promises you await.
return firstValue + secondValue;
})().then(x => console.log(x)); // or .then(console.log)
You can't execute a promise.
You can execute a function.
If you pass a function to a Promise constructor, then it will be executed (by the Promise constructor) immediately.
There is no way to delay the execution of a function passed to a Promise constructor.
You could wrap your calls to new Promise in functions, and then only call the second function when the first promise is resolved.
(Note, however, that in your examples the calls to setTimeout happen after the resolve function is called).
This question already has answers here:
Any difference between await Promise.all() and multiple await?
(6 answers)
Closed 3 years ago.
I have 2 codes
1 code
async function foo() {
const result1 = asyncFunc1();
const result2 = asyncFunc2();
return [result1, result2];
}
2 code
async function foo() {
const [result1, result2] = await Promise.all([
asyncFunc1(),
asyncFunc2(),
]);
return [result1,result2];
}
question
Is there any difference between the two?
As the comments state, you did not await the function calls in the first snippet, so you will get promises as return values. However if you used await, one major difference is that in the first snippet, asyncFunc2 isn't executed until asyncFunc1 is resolved (assuming you use await). Whereas, in the second snippet, asyncFunc2 is executed right after asyncFunc1 regardless of whether it has resolved.
Promise.all will return the results in the order in which you pass the functions.
See docs for Promise.All and Await
As per the comments, there is essentially no difference in the two, other than the fact that you have not awaited the results from the two async functions, so you're gonna end up with just the promise objects. Async functions don't await scoped promises / async code automatically, they just allow you to use the await keyword, which is just stopping the execution until the underlying promise is resolved.
Here's an attempt to illustrate those differences.
What's important to note is that the returned values for the first function are not 1, 2 as would be expected.
const asyncFunc = (a) => {
return new Promise((resolve) => {
setTimeout(() => resolve(a), 1000);
})
}
const asyncFunc1 = () => asyncFunc(1);
const asyncFunc2 = () => asyncFunc(2);
async function foo() {
const result1 = asyncFunc1();
const result2 = asyncFunc2();
return JSON.stringify({ result1, result2 });
}
async function foo2() {
return [result1, result2] = await Promise.all([
asyncFunc1(),
asyncFunc2(),
]);
}
(async () =>{
const el = document.createElement('div');
el.appendChild(document.createTextNode(await foo()));
el.appendChild(document.createTextNode(await foo2()));
document.querySelector('body').appendChild(el);
})();
// {"result1":{},"result2":{}} 1,2
Here's a fiddle to play around with; jsfiddle.
Just find it out! Here is a snippet that shows all major differences:
const timer = ms => new Promise(res => setTimeout(res, ms));
async function one() {
console.log("1 one called");
await timer(2000);
console.log("1 one done");
}
async function two() {
console.log("2 two called");
await timer(1000);
console.log("2 two done");
// throw new Error; // Uncomment to see another interesting behaviour
}
(async function main() {
const startParallel = Date.now();
await Promise.all([one(), two()]);
console.log(`parallel done, took ${Date.now() - startParallel}`);
const startSerial = Date.now();
await one();
await two();
console.log(`serial done, took ${Date.now() - startSerial}`);
})();
I saw this good article to introduce async/await from Google.
However, I couldn't understand why these code run in parallel
async function parallel() {
const wait1 = wait(500);
const wait2 = wait(500);
await wait1;
await wait2;
return "done!";
}
And this run in series
async function series() {
await wait(500);
await wait(500);
return "done!";
}
Why is the key difference between these two methods ?
In my opinion, both of them are await promise and should work the same result.
Here is my test code. Can run in browser console which support async/await.
function wait(){
return new Promise((res)=>{setTimeout(()=>{res()}, 2000)})
}
async function parallel() {
const wait1 = wait();
const wait2 = wait();
await wait1;
await wait2;
return "done!";
}
async function series() {
await wait();
await wait();
return "done!";
}
parallel().then(res => console.log("parallel!"))
series().then(res => console.log("series!"))
======
Thanks for the answers.
But I still have some question. Why exact the async/await means?
In my knowledge, constructing Promise instance would execute directly.
Here is my test code
function wait(){
return new Promise((res)=>{setTimeout(()=>{console.log("wait!");res();}, 2000)})
}
wait()
//PromiseĀ {<pending>}
//wait!
let w = wait()
//undefined
//wait!
let w = await wait()
//wait!
//undefined
async function test(){await wait()}
// undefined
test()
//PromiseĀ {<pending>}
//wait!
So why const wait1 = wait(); inside parallel function execute directly?
By the way, should I open another question to ask these question?
await doesn't cause the Promise or its setTimeout() to start, which seems to be what you're expecting. The call to wait() alone starts them immediately, whether there's an active await on the promise or not.
await only helps you know when the already on-going operation, tracked through the promise, has completed.
So, the difference is just due to when wait() is being called and starting each timeout:
parallel() calls wait() back-to-back as quickly as the engine can get from one to the next, before either are awaited, so the 2 timeouts begin/end at nearly the same time.
series() forces the 2nd wait() to not be called until after the 1st has completed, by having an await act in between them.
Regarding your edit, async and await are syntactic sugar. Using them, the engine will modify your function at runtime, inserting additional code needed to interact with the promises.
A (possible, but not precise) equivalent of series() without await and async might be:
function series() {
return Promise.resolve()
.then(function () { return wait(500) })
.then(function () { return wait(500) })
.then(function () { return "done!"; });
}
And for parallel():
function parallel() {
const wait1 = wait(500);
const wait2 = wait(500);
return Promise.resolve()
.then(wait1)
.then(wait2)
.then(function () { return "done!"; });
}
In parallel(), you call both methods and then await their results while in series() you await the result of the first wait() call before calling the second wait().
Why exact the async/await means? In my knowledge, constructing Promise instance would execute directly.
The Promise instance is returned immediately, i.e. synchronously. But the value of the Promise is evaluated asynchronously by calling the first parameter given to its constructor, a function usually called resolve. This is what you are awaiting for.
The difference is that in parallel, both of the promises are scheduled right after each other.
In series, you wait for the first wait to resolve and then schedule the second wait to be called.
If we expand the methods we'd get something similar to:
function parallel() {
const wait1 = wait();
const wait2 = wait();
// Both wait1 and wait2 timeouts are scheduled
return wait1
.then(() => wait2)
.then(() => "done");
}
function series() {
// The second wait happens _after_ the first has been *resolved*
return wait()
.then(() => wait())
.then(() => "done");
}
I've tried reading guides and tutorials to async/await, but I can't seem to find this addressed anywhere.
Here is the code in question:
var func1 = new Promise((resolve, reject) => {
console.log("Func1");
setTimeout(() => {
resolve(10);
}, 100);
});
var func2 = new Promise((resolve, reject) => {
console.log("Func2");
setTimeout(() => {
resolve(20);
}, 5000);
})
let run = async() => {
let var1 = await func1;
let var2 = await func2;
console.log(var1);
console.log(var2);
}
run();
We see "Func1" and "Func2" get printed immediately, one after the other. 5 seconds later, the timeout specified in func2, we get "10" and "20" printed. So far so good.
But if I change the last bit of code to this:
let run = async() => {
let var1 = await func1;
console.log(var1);
let var2 = await func2;
console.log(var2);
}
Then I see "Func1" immediately printed, but "Func2" as well, even though the console.log(var1) comes before it. After 100ms comes "10", then after 5 seconds comes "20".
From MDN:
The await expression causes async function execution to pause until a Promise is fulfilled or rejected, and to resume execution of the async function after fulfillment.
But it doesn't seem like this is what's happening. If it was, wouldn't we see "Func1", then "10", THEN func2 gets executed, thus printing "Func2" and 5 seconds later we get "20"? func1 should be executed, and once it is resolved (in 100 ms), console.log(var1) should fire. What am I missing here?
The reason for this is that you already ran your promise executors before. Promise executors are evaluated straight away when passed to the Promise constructor, so you'll get the following:
var func1 = new Promise((resolve, reject) => ...); // Logs "Func1"
var func2 = new Promise((resolve, reject) => ...); // Logs "Func2"
let run = async() => {
let var1 = await func1;
console.log(var1); // Logs 10
let var2 = await func2;
console.log(var2); // Logs 20
}
run();
The main problem here is func1 and func2 are not functions; They are promises. Like Jonas W. says, promises will call their callback (resolve, reject) => immediately, and awaiting them just causes them to wait until they are resolved.
You can see your desired result here:
var func1 = () => {
return new Promise((resolve, reject) => {
console.log("Func1");
setTimeout(() => {
resolve(10);
}, 100);
});
}
var func2 = () => {
return new Promise((resolve, reject) => {
console.log("Func2");
setTimeout(() => {
resolve(20);
}, 5000);
});
}
let run = async() => {
let var1 = await func1();
let var2 = await func2();
console.log(var1);
console.log(var2);
}
run();
await basically means enshure that the following value is available before continuing. The promise starts resolving when you create it, it does not matter when it is awaited.
The run function is in synchronous order e.g. the code takes it step by step:
call func1() and wait until there is a reply.
call func2() and wait until there is a reply.
log var1.
log var2.
So the last 2 steps will only run when the call to func2() has completed the promise e.g. the data after the timeout. So it will wait the full 5 seconds until logging both var1 and var2.
The other way is fairly different
1. call func1() and wait until there is a reply.
2. log var1.
3. call func2() and wait until there is a reply.
4. log var2.
Step 2 will wait until step one has returned data e.g. after the 100ms and then will move on to doing the same for step 3 and 4.