Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Request: angular.isPromise helper since $q.prototype !== Promise #14209

Closed
nlwillia opened this issue Mar 10, 2016 · 5 comments
Closed

Request: angular.isPromise helper since $q.prototype !== Promise #14209

nlwillia opened this issue Mar 10, 2016 · 5 comments

Comments

@nlwillia
Copy link

In angular 1.5.0, if I want to test a value to see if it is a promise, I can't just say x instanceof Promise because the promises created by $q do not inherit from the native Promise implementation. I don't know if it would be practical for $q to extend Promise. If not, it would be useful if angular provided an angular.isPromise(p:any): boolean utility function that would return true for both $q and native promises.

@Narretz
Copy link
Contributor

Narretz commented Mar 10, 2016

It can't inherit from promise, because not all supported browsers feature Promise. As for a helper, we don't really want to expose more public helper functions - only if we have internal use for them. So I would say the best idea is to write your own helper fn.

@gkalpak
Copy link
Member

gkalpak commented Mar 10, 2016

BTW, in recent versions (I don't remember exaclty since when), the promises created with $q are instances of $q.
So, your helper would be as simple as:

.factory('isPromise', function isPromiseFactory($q, $window) {
  return function isPromise(val) {
    return (val instanceof $q) || ($window.Promise && (val instanceof $window.Promise));
  };
}) 

@nlwillia
Copy link
Author

#13545 looks like it landed in 1.5.

Promise detection is an issue for external code trying to interop with angular. Just getting access to $q externally is difficult and hackish. angular.injector(['ng']).get('$q') is not going to return the same $q instance as may have been injected in the module that returned the result in question which means that instanceof still won't work and then while also ugly remains the most reliable approach.

The scenario where this is biting me is a jquery widget with an event callback that I'm wiring in angular and returning a router navigation promise. I'm trying to minimize the extent to which the widget knows it's talking to angular, but the lack of a standard promise means then checking. A top-level angular method isn't ideal either, but it would encapsulate the detection logic until someday when hopefully instanceof becomes a viable option. (I guess checking for the presence of a global Promise--which could be native or a polyfill--and adding it to the prototype chain of $q isn't workable?)

@gkalpak
Copy link
Member

gkalpak commented Mar 10, 2016

No, we can't arbitrarily add things to the prototype chain. This might break any time.
.then() seems the way to go then, indeed :)

FWIW, our internal isPromiseLike() helper looks like this:

function isPromiseLike(obj) {
  return obj && isFunction(obj.then);
}

which in native JS translates to:

function isPromiseLike(obj) {
  return obj && (typeof obj.then === 'function');
}

@wesleycho
Copy link
Contributor

This sounds like this isn't likely to be added given comments here - would it be worthwhile to close this issue?

@gkalpak gkalpak closed this as completed Nov 28, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants