Is there a way to determine if an arbitrary js object is an angular promise? I would like to have different behavior based on whether the result of a function is a promise. I can check to see if the object has a 'then' function, but is there a better way?
Checking for .then() sounds reasonable to me, but you may be looking for $q's when(). This will let you handle everything as though it were a promise so you can normalize the behavior of promise and non promise data.
Here's an example using jQuery's promise api (it's almost identical and easier to setup): Live demo (click).
var deferred = new $.Deferred();
deferred.resolve('some promise data.');
var promise = deferred.promise();
x = 'some regular data.';
foo(x);
foo(promise);
function foo(input) {
$.when(input).then(function(data) {
console.log(data);
});
}
Related
When using Promises, why can't triggers for resolve and reject be defined elsewhere in the codebase?
I don't understand why resolve and reject logic should be localized where the promise is declared. Is this an oversight, or is there a benefit to mandating the executor parameter?
I believe the executor function should be optional, and that its existence should determine whether the promise encapsulates resolution or not. The promise would be much more extensible without such mandates, since you don't have to initiate async right away. The promise should also be resettable. It's a 1 shot switch, 1 or 0, resolve() or reject(). There are a multitude of parallel and sequential outcomes that can be attached: promise.then(parallel1) and promise.then(parallel2) and also promise.then(seq1).then(seq2) but reference-privileged players cannot resolve/reject INTO the switch
You can construct a tree of outcomes at a later time, but you can't alter them, nor can you alter the roots (input triggers)
Honestly, the tree of sequential outcomes should be edittable as well.. say you want to splice out one step and do something else instead, after you've declared many promise chains. It doesn't make sense to reconstruct the promise and every sequential function, especially since you can't even reject or destroy the promise either...
This is called the revealing constructor pattern coined by Domenic.
Basically, the idea is to give you access to parts of an object while that object is not fully constructed yet. Quoting Domenic:
I call this the revealing constructor pattern because the Promise constructor is revealing its internal capabilities, but only to the code that constructs the promise in question. The ability to resolve or reject the promise is only revealed to the constructing code, and is crucially not revealed to anyone using the promise. So if we hand off p to another consumer, say
The past
Initially, promises worked with deferred objects, this is true in the Twisted promises JavaScript promises originated in. This is still true (but often deprecated) in older implementations like Angular's $q, Q, jQuery and old versions of bluebird.
The API went something like:
var d = Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
It worked, but it had a problem. Deferreds and the promise constructor are typically used for converting non-promise APIs to promises. There is a "famous" problem in JavaScript called Zalgo - basically, it means that an API must be synchronous or asynchronous but never both at once.
The thing is - with deferreds it's possible to do something like:
function request(param) {
var d = Deferred();
var options = JSON.parse(param);
d.ajax(function(err, value) {
if(err) d.reject(err);
else d.resolve(value);
});
}
There is a hidden subtle bug here - if param is not a valid JSON this function throws synchronously, meaning that I have to wrap every promise returning function in both a } catch (e) { and a .catch(e => to catch all errors.
The promise constructor catches such exceptions and converts them to rejections which means you never have to worry about synchronous exceptions vs asynchronous ones with promises. (It guards you on the other side by always executing then callbacks "in the next tick").
In addition, it also required an extra type every developer has to learn about where the promise constructor does not which is pretty nice.
FYI, if you're dying to use the deferred interface rather than the Promise executor interface despite all the good reasons against the deferred interface, you can code one trivially once and then use it everywhere (personally I think it's a bad idea to code this way, but your volume of questions on this topic suggests you think differently, so here it is):
function Deferred() {
var self = this;
var p = this.promise = new Promise(function(resolve, reject) {
self.resolve = resolve;
self.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}
Now, you can use the interface you seem to be asking for:
var d = new Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
d.then(...) // can use .then() on either the Deferred or the Promise
d.promise.then(...)
Here a slightly more compact ES6 version:
function Deferred() {
const p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}
Or, you can do what you asked for in your question using this Deferred() constructor:
var request = new Deferred();
request.resolve();
request.then(handleSuccess, handleError);
But, it has the downsides pointed out by Benjamin and is not considered the best way to code promises.
In this example I'm testing whether an element is located at the bottom of the page. I'm using the promises in Protractor/Webdriver, but I think I'm using it wrong because I don't think it's supposed to look this messy.
describe('Element', function(){
it('should be placed at bottom', function(){
element(by.id('page').getSize().then(function(dimP){
element(by.id('element').getLocation().then(function(locE){
element(by.id('element').getSize().then(function(dimE){
expect(locE.y + dimE.height).toEqual(dimP.height);
})
});
});
})
});
How can I do this in a cleaner way? I'm using Protractor version 2.1.0.
I have tried to do like this:
expect(element(by.id('page').getSize().height).toEqual(1000);
But it says Expected undefined to equal 1000. So it seems like I can't use return values as explained here: https://github.com/angular/protractor/blob/master/docs/control-flow.md
(I am using a page object in my actual test, so the variables are not as ugly as in the example.)
Since getSize() and getLocation() both return promises and you need actual values, you have to resolve all of the promises, either explicitly with then(), or let expect() implicitly do this for you.
I'm actually understanding your question as "How to flatten a promise chain in Protractor?". This is there promise.all() would help to resolve multiple promises at once which would save you from writing multiple nested then() callbacks:
var elm = element(by.id('element')),
page = element(by.id('page'));
var promises = [elm.getSize(), elm.getLocation(), page.getSize()];
protractor.promise.all(promises).then(function (values) {
expect(values[0].height + values[1].y).toEqual(values[2].height);
});
See also:
Flattening Promise Chains
How do I reference a promise returned from a chained function?
How do I access previous promise results in a .then() chain?
I know how to create a promise in Kris Kowal's q with var defer = Q.defer();, calling defer.resolve(); and/or defer.reject() and return defer.promise. But reading the docs, it seem's there is an alternative way to create a promise...
From the docs:
Q.Promise(resolver)
Synchronously calls resolver(resolve, reject, notify) and
returns a promise whose state is controlled by the functions passed to
resolver. This is an alternative promise-creation API that has the
same power as the deferred concept, but without introducing another
conceptual entity.
If resolver throws an exception, the returned promise will be rejected
with that thrown exception as the rejection reason.
This is, what I've tried:
function () {
return Q.Promise(function (resolve, reject) {
(...do something...)
resolve(5); // or: reject(error);
});
}
But this doesn't work as expected!
Can someone give an example, how to use Q.Promise?
UPDATE:
Thanks for downvoting! I asked for an usage example, therefore a simple "you use it in a correct way" is more helpful! Btw: it fails silently and yes, I attached an error handler!
The reason, why the function is unnamed, is that I use it together with map and reduce to create a delayed chain of promises, but it seems, the resolver functions are never called... Therefore I asked for a (again) usage example...
Looking at your 2 examples, I'm guessing you are doing this:
var q = require('q');
Therefore Q.Promise won't work, but rather q.Promise will.
I have a number of async tasks that need to be completed, so I'm using promises.
I need to detect when each one of the promises has been executed (both resolved and rejected). I must not continue execution until that point.
I was using something like this:
$.when(promise1, promise2, ...).always();
But this code is wrong, because the when method has lazy evaluation, and it returns as soon as one of the promises fails. So the always callback also runs as soon as one of the promises fail.
I was thinking in coding a workaround, but this use case is so common that maybe somebody has done it already, or maybe there's even a way of doing this using just jQuery (if not, it would be nice to add a Promise.whenNonLazy or a Promise.when(promise1, promise2, ..., false) in the future.
Is this possible?
More sophisticated promise libraries have an allSettled() function like Q or Promise.settle like Bluebird.
In jQuery, you could implement such a function yourself as well and extend the $ namespace with it, but that will only be necessary if you need it often and performance-optimized.
A simpler solution would be to create a new promise for each of the ones you are waiting for, and fulfilling them even when the underlying one is rejected. Then you can use $.when() on them without problems. In short:
// using Underscore's .invoke() method:
$.when.apply(null, _.invoke(promises, "then", null, $.when)).done(…)
More stable:
$.when.apply($, $.map(promises, function(p) {
return p.then(null, function() {
return $.Deferred().resolveWith(this, arguments);
});
})).then(…);
You might change the then callbacks a bit to distinguish between fulfilled and rejected results in the final done.
Smithy,
First let's assume your promises are in an array.
var promises = [....];
What you appear to want is .when() applied to some transform of these promises, such that any rejected promise is converted to resolved, whilst being transparent to promises that are already resolved.
The required operation can be written very succinctly as follows :
$.when.apply(null, $.map(promises, resolvize)).done(...);
//or, if further filtering by .then() is required ...
$.when.apply(null, $.map(promises, resolvize)).then(...);
where resolvize is the transform mechanism.
So what should resolvize(), look like? Let's exploit the characteristics of .then() to make the distinction beteween a resolved and a rejected promise, and respond accordingly.
function resolvize(promise) {
//Note: null allows a resolved promise to pass straight through unmolested;
return promise.then(null, function() {
return $.Deferred().resolve.apply(null, arguments).promise();
});
}
untested
With resolvize in some outer scope, it can be made available to be used in a $.when.apply($.map(promises, resolvize)) expression wherever it is needed. This is most likely adequate, without going to the extent of extending jQuery with a new method.
Regardless of how the transform is achieved, you end up with a potential issue; namely knowing for each argument of the .done() callback, whether its corresponding promise was originally resolved or rejected. That's the price you pay for converting rejection to resolution. You may, however, be able to detect the original status from the parameter(s) with which the original promises were resolved/rejected.
That's an interesting property of always - I hadn't expected that behaviour.
I suppose you could use a master, top-level deferred to monitor the states of the main deferreds, which is resolved only once the main deferreds are all either resolved or rejected. Something like:
//set up master deferred, to observe the states of the sub-deferreds
var master_dfd = new $.Deferred;
master_dfd.done(function() { alert('done'); });
//set up sub-deferreds
var dfds = [new $.Deferred, new $.Deferred, new $.Deferred];
var cb = function() {
if (dfds.filter(function(dfd) {
return /resolved|rejected/.test(dfd.state());
}).length == dfds.length)
master_dfd.resolve();
};
dfds.forEach(function(dfd) { dfd.always(cb); });
//resolve or reject sub-deferreds. Master deferred resolves only once
//all are resolved or rejected
dfds[0].resolve();
dfds[1].reject();
dfds[2].resolve();
Fiddle: http://jsfiddle.net/Wtxfy/3/
From what I have understood there are three ways of calling asynchronous code:
Events, e.g. request.on("event", callback);
Callbacks, e.g. fs.open(path, flags, mode, callback);
Promises
I found the node-promise library but I don’t get it.
Could someone explain what promises are all about and why I should use it?
Also, why was it removed from Node.js?
Since this question still has many views (like mine) I wanted to point out that:
node-promise looks rather dead to me (last commit was about 1 year ago) and contains nearly no tests.
The futures module looks very bloated to me and is badly documented (and I think that the naming conventions are just bad)
The best way to go seems to be the q framework, which is both active and well-documented.
Promises in node.js promised to do some work and then had separate callbacks that would be executed for success and failure as well as handling timeouts. Another way to think of promises in node.js was that they were emitters that could emit only two events: success and error.
The cool thing about promises is you can combine them into dependency chains (do Promise C only when Promise A and Promise B complete).
By removing them from the core node.js, it created possibility of building up modules with different implementations of promises that can sit on top of the core. Some of these are node-promise and futures.
A promise is a "thing" which represents the "eventual" results of an operation so to speak. The point to note here is that, it abstracts away the details of when something happens and allows you to focus on what should happen after that something happens. This will result in clean, maintainable code where instead of having a callback inside a callback inside a callback, your code will look somewhat like:
var request = new Promise(function(resolve, reject) {
//do an ajax call here. or a database request or whatever.
//depending on its results, either call resolve(value) or reject(error)
//where value is the thing which the operation's successful execution returns and
//error is the thing which the operation's failure returns.
});
request.then(function successHandler(result) {
//do something with the result
}, function failureHandler(error) {
//handle
});
The promises' spec states that a promise's
then
method should return a new promise that is fulfilled when the given successHandler or the failureHandler callback is finished. This means that you can chain together promises when you have a set of asynchronous tasks that need to be performed and be assured that the sequencing of operations is guaranteed just as if you had used callbacks. So instead of passing a callback inside a callback inside a callback, the code with chained promises looks like:
var doStuff = firstAsyncFunction(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
success: function(data) {
resolve(data);
},
error: function(err) {
reject(err);
}
});
};
doStuff
.then(secondAsyncFunction) //returns a promise
.then(thirdAsyncFunction); //returns a promise
To know more about promises and why they are super cool, checkout Domenic's blog : http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/
This new tutorial on Promises from the author of PouchDB is probably the best I've seen anywhere. It wisely covers the classic rookie mistakes showing you correct usage patterns and even a few anti-patterns that are still commonly used - even in other tutorials!!
http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
Enjoy!
PS I didn't answer some other parts of this question as they've been well covered by others.
Mike Taulty has a series of videos, each of them less than ten minutes long, describing how the WinJS Promise library works.
These videos are quite informative, and Mike manages to show the power of the Promise API with a few well-chosen code examples.
var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });
promise = promise.then(
function (xhr) {
},
function (xhr) {
// handle error
});
The treatment of how exceptions are dealt with is particularly good.
In spite of the WinJs references, this is a general interest video series, because the Promise API is broadly similar across its many implementations.
RSVP is a lightweight Promise implementation that passes the Promise/A+ test suite. I quite like the API, because it is similar in style to the WinJS interface.
Update Apr-2014
Incidentally, the WinJS library is now open source.
Another advantage of promises is that error handling and exception throwing and catching is much better than trying to handle that with callbacks.
The bluebird library implements promises and gives you great long stack traces, is very fast, and warns about uncaught errors. It also is faster and uses less memory than the other promise libraries, according to http://bluebirdjs.com/docs/benchmarks.html
What exactly is a Promise ?
A promise is simply an object which represents the result of an async operation. A promise can be in any of the following 3 states :
pending :: This is the initial state, means the promise is neither fulfilled nor rejected.
fulfilled :: This means the promise has been fulfilled, means the value represented by promise is ready to be used.
rejected :: This means the operations failed and hence can't fulfill the promise.
Apart from the states, there are three important entities associated to promises which we really need to understand
executor function :: executor function defines the async operation which needs to be performed and whose result is represented by the promise. It starts execution as soon as the promise object is initialized.
resolve :: resolve is a parameters passed to the executor function , and in case the executor runs successfully then this resolve is called passing the result.
reject :: reject is another parameter passed to the executor function , and it is used when the executor function fails. The failure reason can be passed to the reject.
So whenever we create a promise object, we've to provide Executor, Resolve and Reject.
Reference :: Promises
I've been also looking into promises in node.js recently. To date the when.js seems to be the way to go due to its speed and resource use, but the documentation on q.js gave me a lot better understanding. So use when.js but the q.js docs to understand the subject.
From the q.js readme on github:
If a function cannot return a value or throw an exception without
blocking, it can return a promise instead. A promise is an object that
represents the return value or the thrown exception that the function
may eventually provide. A promise can also be used as a proxy for a
remote object to overcome latency.
Promise object represents the completion or failure of an asynchronous operation.
So in order to implement a promise, you need two parts:-
1.Creating Promise:
The promise constructor accepts a function called an executor that has
2 parameters resolve and reject.
function example(){
return new Promise (function(resolve , reject){ //return promise object
if(success){
resolve('success'); //onFullfiled
}else{
reject('error'); //onRejected
}
})
}
2.Handling Promise:
Promise object has 3 methods to handle promise objects:-
1.Promise.prototype.catch(onRejected)
2.Promise.prototype.then(onFullfiled)
3.Promise.prototype.finally(onFullfiled,onRejected)
example.then((data) =>{
//handles resolved data
console.log(data); //prints success
}).catch((err) => {
//handles rejected error
console.log(err); //prints error
})