Reputation: 13
I am new to Javascript and nodejs. While trying to understand how promises and callbacks work, i tried calling a function in a 'for' loop as shown below. What i was trying to achieve is to print 'i' value every 2 seconds using promises. However, the program waits for 2 seconds and prints i value 3 times and exits.
for(let i = 0; i < 3 ; i++){
func(callback,i);
}
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
Can anybody please help me understand why this is happening?
Upvotes: 1
Views: 1950
Reputation: 2162
Here are some functions which help you understand how promises work with Arrays, where we make common mistakes.
function promiseFunction(v) {
return new Promise((resolve) => {
setTimeout(() => resolve(v), 1000);
});
}
function f1() {
[1, 2, 3, 4]. forEach(async(i) => {
const v = await promiseFunction(i);
console.log(`-f1 v- ${v}<br/>`);
});
console.log('all done<br/>');
}
async function f2() {
await Promise.all([1, 2, 3, 4].map(async(i) => {
const v = await promiseFunction(i);
console.log(`-f2 v- ${v}<br/>`);
}));
console.log('all done<br/>');
}
async function f3() {
await [1, 2, 3, 4].reduce((p, i) => {
return p.then(async () => {
const v = await promiseFunction(i);
console.log(`-f3 v- ${v}<br/>`);
});
}, Promise.resolve());
console.log('all done<br/>');
}
async function func() {
console.log('f1');
await f1();
console.log('f2');
await f2();
console.log('f3');
await f3();
}
func();
f1() will print all done
first and then print 1,2,3,4 at once after a second.
f2() will print 1,2,3,4 at once after a second then print all done
.
f3() will print 1,2,3,4 in every second, and then print all done
.
Upvotes: -1
Reputation: 15472
You can just wrap your loop with async
immediately executed function and add await
within it (as was already suggested here):
(async () => {
for(let i = 0; i < 3 ; i++){
await callback(i);
}
})();
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
Here is my original answer before Bergi's edit:
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
Upvotes: 3
Reputation: 3241
You are pretty close. The missing information is async
functions (your func()
) implicitly returns an AsyncFunction
object which implicitly returns a Promise itself too (doc).
Your code using immediately invoked function expression would be
(async () => {
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
})()
async function func(callback,i){
await callback(i);
}
function callback(i){
return new Promise((res,rej) =>{
setTimeout(()=>{
console.log('i = ',i)
res();
}, 2000);
})
}
Please note now in most of the browsers is natively available the construct for await..of
(doc). You can try experimenting this one too.
Upvotes: 3
Reputation: 564
You need to wait for async function to complete
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
But since you can't use await
keyword in the global scope, you will need to wrap your for
loop in an async function, and than call it
async function myTest(){
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
}
myTest()
Upvotes: -1
Reputation: 50
You async function func also returns a promise so you need the await keyword before its call.
for(let i = 0; i < 3 ; i++){
await func(callback,i);
}
Upvotes: -2