As I know, Promises are used to represent success/failure of an asynchronous operation. When I am looking into one of my project, all the functions are wrapping the final result in 'Promise.resolve'. I am not understanding, what is the use of wrapping all the function results in 'Promise.resolve'. Is there any use case here?
For example, all the functions are following below template.
process = (data) => {
//Perform some operations.
return Promise.resolve(result);
}
The only reason to use Promise.resolve is converting a value that might be a promise to a promise.
Promise.resolve(value) is a convenience method that does new Promise(resolve => resolve(value). If the value is a promise it will be returned, if it is a promise from a userland promise library it will be converted to a native promise. If it is a plain value it will be converted for a promise fulfilled with that value.
Promise.resolve(5); // returns a promise fulfilled with the number 5.
This is useful in several cases, for example:
- If a function might return a promise, it should always return a promise - so for example if you have a cached value it might need to be Promise.resolved.
- If there are multiple implementations of functionality and some are synchronous - it creates a uniform interface.
Note that in practice with async functions this is not needed so much anymore since an async function always returns a promise - even if you return a plain value (in fact, whatever you return from an async function is Promise.resolved implicitly).
Also note that in particular you shouldn't make functions return promises if all they do is synchronous computation since a function returning a promise implies I/O in JavaScript.
Related
Is there a simple and elegant way to determinate if variable is promise or object in javascript (es6)?
I have a variable
let payment;
and at one time in app, it can be either promise or object with real values. I know I can test it it contains some properties like
if (payment.amount)
but this doesn't seems like an elegant solution to me, because properties (data structure) can change in time. Till now I was using
if (typeof payment === 'object')
but I've just figured out, that promises are basically also objects. So this condition is always true.
Is it possible to tell if it's a promise or object with real data?
Don't try to find out. Just make it always a promise.
payment = Promise.resolve(payment);
Promise.resolve creates a new promise object. If the value passed is itself a promise, the is resolved or rejected when the original one is. If it is anything else, the new promise is resolved immediately with that value.
As with all other native objects, you can use instanceof with the Promise constructor:
if (payment instanceof Promise)
However, if you don't know whether it's a native promise or from a custom library, you will usually want to detect a thenable by checking whether it has a .then method.
But you never really need to distinguish them (other than for debugging purposes). If there is a chance that something is a promise, you will always need to wait for, and construct a promise from it anyway. You don't need to do the distinction yourself, you can just use Promise.resolve to cast either promise, thenable or plain object to a promise of your favoured implementation - that's how Promise interoperability was designed in the first place, so it will absolutely work.
const promise = Promise.resolve(payment).then(value => {
// value: always a plain value
}); // promise: always a promise
Check if it has a property then that is a function:
if(payment != null && typeof payment.then === 'function')
// is a promise
else
// is not a promise
As far as I know, this is the only proper way to check if something is a promise (or a "promise-like" thenable), taking into account all different possible promise implementations.
In case you are worried about using await on a plain-old function (rather than a Promise), it's actually okay to do that in ES6. The await gets ignored - no errors are thrown.
This may resolve your need to actually perform the comparison at all (as it did in my case when I first found this question)
payment instanceof Promise
or this:
payment.constructor.toString().indexOf('Promise') > -1
payment.constructor === Promise
I'm trying to understand how promises work, so general idea is quite clear, but currently I'm stuck with all() method. I know, it used to make a promise for an array of other promises, which will be resolved when all promises from the array will resolved or will be rejected when any of the promises from the array will rejected. Here is my code snippet:
var qu = require('q');
var proArr = [];
for(var i = 0; i < 4; i++) {
var tmpDef = qu.defer();
(function(index, tmpDef) {
setTimeout(function() {
console.log('Timeout ' + index + ' has triggered!');
tmpDef.resolve();
}, (i + 1) * 1000);
proArr.push(tmpDef.promise);
})(i, tmpDef);
}
qu.all(proArr).then(function() {
console.log('All timeouts has passed with Q.all()!');
return 'some result';
});
qu.defer().promise.all(proArr).then(function() {
console.log('All timeouts has passed with promise.all()!');
return 'some result';
});
For this snippet a promise, which returned by qu.all() method will be resolved when all timeouts will be triggered, but a promise, which returned by qu.defer().promise.all() method will stay in pending state even if all timeouts will be triggered. So what the method Promise.prototype.all() have to be used for? And how it differs from Q.all() method?
Also I've looked in Q library sources, and here is a code for Promise.prototype.all() method:
Promise.prototype.all = function () {
return all(this);
};
As I can understand, this method calls Q.all() with an instance of current promise as an argument, but why? Don't the method Q.all() have to accept an array of promises? So I'll be very appreciated for clarification of all this moments.
Don't the method Q.all() have to accept an array of promises?
No, in fact the Q.all method also can take a promise for an array of promises. You can see that in the code well, it does call Q.when on the input. This might seem a bit useless, but it's a more forgiving API and apparently simiplifies the implementation of Promise.prototype.all.
What is the difference between Q.all() and Promise.prototype.all()?
Let's get back to our simpler mental model. Q.all is a static function that takes an array of promises and returns you a promise for an array of all results.
The .all prototype method is simply convenience. Instead of writing
….then(Q.all).…
you can use
….all().…
in a promise chain - these are exactly equivalent. Notice that the .all prototype method does not take any parameters - it does get the array from promise it is called on.
a promise, which returned by Q.defer().promise.all(proArr) method will stay in pending state even if all timeouts will be triggered
Yes. That's for two reasons:
Q.defer().promise is a promise that never resolves (and since you've thrown away the deferred, you never can). The chain just doesn't even advance to the .all(…) invocation.
As established above, the prototype method you're calling here doesn't take any arguments. The proArr is simply ignored.
If you want to use it, you can use the following though:
Q(proArr).all().…
I have read the documentation of $q.when in the angularjs official docs, but I don´t understand yet what is the purpose of $q.when and its way to manage a response.
$q.when takes a promise or a plain value and converts it to a promise. If it already was a promise it simply returns it.
It is useful if you don't know whether the object you're dealing with is a promise or not. For example, you might have an if/else statement where one path returns a promise but another path returns a value directly. In that case, it would be good to use $q.when to handle the return such that you get a value out of it whether it's a promise or not.
For example:
function getData(){
if(cachedData) return $q.when(cachedData); // converts to promise
else return $http.get("/dataUrl"); // make HTTP request, returns promise
}
I'm writing a nodejs thing, and trying the Pacta promise library for fun. Pacta's interface is "algebraic," but I don't have any experience with that paradigm.
I'd like to know what is the "Pacta way" to accomplish the same thing as
$.when.apply(undefined, arrayOfThings)
.then(function onceAllThingsAreResolved(thing1Val, thing2Val, ...) {
// code that executes once all things have been coerced to settled promises
// and which receives ordered resolution values, either as
// separate args or as a single array arg
}
That is, given an array, an iterator function that returns a promise, and a callback function, I'd like to map the iterator onto the array and provide an array of the resolution values (or rejection reasons) to the callback once all the promises have been settled.
If there isn't an idiomatically algebraic way to express this, I'd be just as interested to know that.
EDIT: updated use of $.when to properly accommodate an array, per #Bergi.
Pacta's interface is "algebraic," but I don't have any experience with that paradigm.
ADTs are type theory constructs that represent nested data types, like a Promise for Integer. They are heavily used in functional programming, a flavour where you always know the types of your expressions and values. There are no intransparent, implicit type coercions, but only explicit ones.
This is completely contrary to jQuery's approach, where $.when() and .then() do completely different things based on the types (and number) of its arguments. Therefore, translating your code is a bit complicated. Admittedly, Pacta doesn't have the most useful implementation, so we have to use some own helper functions to do this.
Assume you have an array of (multiple) promises, and your then callback takes the arguments and returns a non-promise value:
arrayOfPromises.reduce(function(arr, val) {
return arr.append(val);
}, Promise.of([])).spread(function (…args) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as separate args
});
If your callback does not take multiple arguments, use map instead of spread:
arrayOfPromises.reduce(function(arrp, valp) {
return arrp.append(valp);
}, Promise.of([])).map(function (arr) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as an array
});
If your callback does return a promise, use chain instead of map:
arrayOfPromises.reduce(function(arr, val) {
return arr.append(val);
}, Promise.of([])).chain(function (arr) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as an array
});
If you don't know what it returns, use then instead of chain. If you don't know what it returns and want to get multiple arguments, use .spread(…).then(identity).
If your array contains promises mixed with plain values, use the following:
arrayOfThings.reduce(function(arrp, val) {
var p = new Promise();
Promise.resolve(p, val);
return arrp.append(p);
}, Promise.of([])).…
If your array contains only a single or no (non-thenable) value, use
Promise.of(arrayOfThings[0]).…
If your array contains anything else, even $.when would not do what you expect.
Of course, promises that resolve with multiple values are not supported at all - use arrays instead. Also, your callback will only be called when all promises are fulfilled, not when they're settled, just as jQuery does this.
I'm after a function that would return a resolved value of a promise. Failing gracefully is definitely a bonus, but it's an assumed precondition that when the function is called the promise is ready to be resolved.
While I'm working with webdriver.js promise implementation which allows the queue manipulations similar to below, I don't want to get too lost in semantics of queues/chains etc. For that reason alone, here is some pseudocode to cover what I'm trying to achieve:
var inputs = [...], outputs;
outputs = inputs.map(function(input){
//queue some async tasks to be performed with input
queue.enqueue(...);
//I can't return the *output* value here yet, naturally, so instead
return promise;
});
//now I'll add another task to the same queue
//this means that by the time this task is run
//the async tasks above would have been executed
//and the promises would be "resolvable"... right?
queue.enqueue(function(){
console.log(outputs); //>an array of promises
console.log(doSomeMagic(outputs)); //>resolved values as needed <<<
});
NB: afaik Q.all() would not do what I'm after - it takes an array of promises and returns a promise of an array, not its resolved value. I'm only happy to be proved wrong.
For anyone else looking for an answer based on the title of the question the following works with ES 2017+ to take an array of promises and return an array of values:
var arrayOfValues = await Promise.all(arrayOfPromises)
The only way to get the eventual value for a promise is with then. If a function performs work asynchronously, it must return a promise and under no circumstances can it return a plain value. To do so, it would necessarily have to block the thread of execution until the work completes, which is only possible with threads or fibers, which entrain the perils of deadlock and interleaving hazards.
As such, Q.all is in fact the method you need, except to follow up with then to get the eventual value.
Q.all(inputs.map(function (input) {
return promiseForOutput; // however you go about this
}))
.then(function (outputs) {
// at this event, outputs is an array of output values
});
There are ways to cheat, of course. promise.inspect() will return an object describing the state of the promise, like {state: "fulfilled", value: value} if it’s ready, or {state: "rejected", error} if it failed, or {state: "pending"}, if it is not yet ready. If, as you say, you are guaranteed that the outputs promise, returned by Q.all has been fulfilled, you can do this:
outputs = outputs.inspect().value
I don’t recommend this. The best way to know that a promise is resolved is to use then.
You could also just push values onto an outputs array of your making if you can also guarantee that all the outputs are ready through some external means.
var endResult = Q.defer();
var outputs = [];
inputs.forEach(function (input) {
outputPromise.then(function (output) {
outputs.push(output);
check();
}, endResult.reject);
});
check();
function check() {
if (outputs.length === inputs.length) {
// manipulate outputs directly, they are ready
endResult.resolve();
}
}
return endResult.promise;
The best means, however, is to just use Q.all(outputs).then to get an event that is guaranteed to be after all the outputs are ready.
Since you in general never know whether promises are resolved or not, you cannot simply transform them into a plain value. Q.all must return a promise since it cannot extract the values array from the async context. The only time you know that a promise has a value is in the success handler, and there you're getting the value anyway. You should not use another event system that tells you when a promise has settled - use the promise itself.
So instead of using queue.enqueue, just put Q.all(outputs).then(function(values){ /* do something */ }). However, if you cannot work around that, you might have a look at the Promise inspect debugging method: _.pluck(_.invoke(outputs, "inspect"), "value"). But notice that it might be easier not to store the values in promises then.