Reputation: 1983
I ran into a bug in my code that puzzled me for a long time and am looking for some clarification.
In this code, the commented out inner promise was causing a problem. The Promise.all() at the end was continuing as soon as the setTimeout hit, not after the resolve inside the timeout.
Wrapping the async code with a promise fixes the flow problem, but why is this?
Essentially, why can't we just run normal async code in a .then() chain, an return a Promise.resolve() at the end of the async callback?
var asyncPromise = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('Async Promise done');
resolve();
}, 1000);
});
};
var generateSignupPromises = function(qty) {
var promiseArray = [];
for (var i = 1; i <= qty; i++) {
promiseArray.push(
function() {
return asyncPromise()
.then(function() {
console.log('Before Timeout');
//Uncommenting this fixes the issue
//return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('After Timeout');
//resolve();
return Promise.resolve();
}, 500);
//})
});
}
);
}
return promiseArray;
};
var test = generateSignupPromises(1);
Promise.all([test[0]()])
.then(function() {
console.log('Done');
});
Link to running code: http://www.es6fiddle.net/imfdtuxc/
Upvotes: 2
Views: 2668
Reputation: 664307
why can't we just run normal async code in a .then() chain, an return a Promise.resolve() at the end of the async callback?
You perfectly can. But any value - be it a promise or whatever - being return
ed from a plain asynchronous callback is just ignored as usual.
There is nothing that starting the asynchronous action inside a then
callback changes about this, setTimeout
just doesn't return a promise - and the then
won't know about anything asynchronous happening that it could wait for.
If you want to return a promise from a callback and get another promise for that eventual result, it has to be a then
callback:
asyncPromise()
.then(function() {
return new Promise(function(resolve, reject) {
// ^^^^^^
setTimeout(resolve, 500);
}).then(function() {
// ^^^^^^^^^^^^^^^
return Promise.resolve();
});
});
Upvotes: 5
Reputation: 1400
Then is a sync function so if you want to do async task inside then, you has to return a Promise.
Also, Promise.all expect an array of promises. Not an array of an array.
var asyncPromise = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('Async Promise done');
resolve();
}, 1000);
});
};
var generateSignupPromises = function(qty) {
var promiseArray = [];
for (var i = 1; i <= qty; i++) {
promiseArray.push(
function() {
return asyncPromise()
.then(function() {
console.log('Before Timeout');
//Uncommenting this fixes the issue
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('After Timeout');
resolve();
//return Promise.resolve();
}, 500);
})
});
}
);
}
return promiseArray;
};
var test = generateSignupPromises(1);
Promise.all([test[0]()])
.then(function() {
console.log('Done');
});
http://www.es6fiddle.net/imfe2sze/
Upvotes: 0