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
Related
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).
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);
This question already has answers here:
Combination of async function + await + setTimeout
(17 answers)
Closed 3 years ago.
I need to run various steps in a function but steps have to be run in a specific order. I tried to implement an Async function as follow:
async function test() {
await setTimeout(function() { console.log('1'); }, 5000);
await setTimeout(function() { console.log('2'); }, 2000);
console.log('3');
}
test();
The expected results in the console should be 1, 2, 3 but I get 3, 2, 1.
It seems that the await parameter is ignored.
EDIT
The setTimeout function is used in the illustrative example above only to simulate a heavy task. In my project, I will not use it. Indeed, I need to connect to a database then reformat the results before moving to the next steps. Even by including the async-await, 2 is logged-in before 1. In other words, empty lists are passed to my graphic because the async-await is not taken into consideration. Here my current code:
async function refreshData() {
myLabel = [];
myValues = [];
myJSON = [];
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database(fullPath + '/annex/data.db');
await new Promise(resolve => {
db.each('SELECT firstName, age FROM Info;', function(err, row) {
console.log('1');
myLabel.push(row.firstName);
myValues.push(row.age);
myJSON.push(JSON.stringify(row));
});
resolve(myValues);
resolve(myLabel);
resolve(myJSON);
});
console.log('2');
db.close();
popChart(myLabel, myValues);
popTable();
}
You can write a wait function:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
async function test() {
console.log('1');
await wait(5000);
console.log('2');
await wait(2000);
console.log('3');
}
test();
I've used the following
function wait(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
and then you just await this function in your method.
using this:
async function test() {
await new Promise(resolve => {
setTimeout(function() { console.log('1'); resolve(); }, 5000)
});
await new Promise(resolve => {
setTimeout(function() { console.log('2'); resolve(); }, 2000)
});
console.log('3');
}
test();
For using await on a function & waiting till the function executes, it must be running on a promise, so you can create a new function delay which calls setTimeout within itself but runs on promise, so it will return once the console is logged after timeout & the calling function will hold the execution until it gets the promise resolved
Read this for better understanding with more examples
function delay (val,time){
return new Promise((resolve,reject)=>{
setTimeout(function() { console.log(val); resolve(true) }, time);
});
}
async function test() {
await delay('1',5000);
await delay('2',2000);
console.log('3');
}
test();
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.
I would expect the output for the following snippet to be 1, 2, 3, 4. But, the actual output order is 1, 4, 3, 2.
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
console.log(1);
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
console.log(2);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
console.log(3);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
console.log(4);
});
});
http://www.es6fiddle.net/imu5bhoj/
Everything I've read about promises indicates it should be possible to get the desired order in a 'flat' chain like this. Apparently I'm missing some detail? Could someone help point me in the right direction?
Here's a fiddle (http://www.es6fiddle.net/imu6vh1o/) for how to do it in a non-flat way, but it's harder to reason about and makes sequential chaining awkward.
I've searched similar issues on stack overflow but none of them answer the question generically using a straightforward example (that I could find).
You just attached three .then() handlers to the exact same self.promiseChain promise. This is branching, not chaining. With promises, those are very different behaviors. Those are three handlers that will all be called one immediately after the other (without waiting for results) when self.promiseChain is resolved. So, the resulting three async operations will run in parallel and finish whenever they finish, thus the results you see.
If you wanted these four operations to be sequenced, then you have to actually chain them one to another, not all chained onto the same promise. Remember .then() returns a new promise and it is that returned promise that you want to chain to in order to sequence things.
You are doing this:
var p = somePromise();
p.then(fn1);
p.then(fn2);
p.then(fn3);
This will trigger fn1, fn2 and fn3 at basically the same time and fn2 will not wait for the fn1 promise to resolve.
If you want to sequence the operations, then you want this type of logic:
var p = somePromise();
p.then(fn1).then(fn2).then(fn3);
This will not execute fn2 until the fn1 promise is done and will not execute fn3 until the fn2 promise is done - thus sequencing the async operations.
Here's how it would be if they were actually sequenced one after another. You can actually run this snippet (but have patience because it takes 10 seconds to run):
var self = {};
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
log(1);
});
var p = self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
log(2);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
log(3);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
log(4);
});
});
p.then(function() {
// last promise is done now
log("all done");
});
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
See these other similar answers:
Execute native js promise in series
Understanding javascript promises; stacks and chaining
Is there a difference between promise.then.then vs promise.then; promise.then