Reputation: 3441
I'm having a (seemingly fundamental) problem understanding promises. First the code:
'use strict';
var Q = require("q");
var mockPromise = function (statement) {
var deferred = Q.defer();
console.log("I'm running before I'm queued ...");
setTimeout(function () {
deferred.resolve(statement);
}, 5000);
return deferred.promise;
};
var promises = [
mockPromise("1st statement"),
mockPromise("2nd statement"),
mockPromise("3rd statement")
];
Q.all(promises)
.then(function (results) {
console.log(results);
});
Each promise function gets invoked upon adding it to the promise array, as opposed to when Q.all is called as I thought.
What am I not getting here?
How do I queue an array of promises without immediately invoking said promises?
Upvotes: 0
Views: 621
Reputation: 405
It seems the confusion is that you understand the promise API to be designed for lazy evaluation, which is not the case.
Promises are a way of handling long running requests, they were designed to start IMMEDIATELY to minimize waiting time, and to utilize chaining and joining to clarify how the results of these long running requests should be processed.
You might try to utilize the api Q-Lazy which allows you to delay invocation of promises until they have been subscribed to.
Upvotes: 2
Reputation: 5549
Promises are objects. They are not 'executed'. They are 'resolved' or 'rejected'. When you create the array, you are executing the mockPromise() function three times. This function is immediately executed in that point of the code.
The mockPromise() function creates a deferred and returns the associated promise. It also sets a timer to resolve the returned promise in the future.
Q.all() just waits for the 3 promises to be 'resolved'. (technically it returns a new promise that will be resolved when the 3 previous promises are resolved)
If you want to execute the three async functions one after the other, I would recommend using the excellent async.js library. It provides many async flow control primitives. In your case you may be interested in series or waterfall methods.
Upvotes: 2
Reputation: 29916
Let me show a sample using standard promises. They work pretty much the same as Q promises:
function mockPromise(value) {
return new Promise(resolve => {
console.log("I'm not running before I'm queued ...");
setTimeout(() => {
resolve(value);
}, 1000);
});
}
mockPromise("1st promise").then(x => {
console.log(x);
return mockPromise("2nd promise");
}).then(x => {
console.log(x);
return mockPromise("3nd promise");
}).then(x => {
console.log(x);
});
Upvotes: 0
Reputation: 5215
You'd normally defer asynchronous functionality, not just a value. For example:
'use strict';
var Q = require("q");
var mockPromise = function (statement) {
var deferred = Q.defer();
console.log("I'm running before I'm queued ...");
setTimeout(function () {
deferred.resolve(statement());
}, 5000);
return deferred.promise;
};
var promises = [
mockPromise(function() {
console.log("running1");
return "1st statement";
}),
mockPromise(function() {
console.log("running2");
return "2nd statement";
}),
mockPromise(function() {
console.log("running3");
return "3rd statement";
}),
];
Q.all(promises)
.then(function (results) {
console.log(results);
});
Note that the deferred functionality is going to run regardless of whether you ever call a .then
on a promise.
Upvotes: 0