[英]How can I tell if an object is an Angular $q promise?
我的项目中有一个预先存在的非Angular API库。 它有一个.request
方法,它返回jQuery.Deferred promises。 我创建了一个简单的Angular服务,它包装了.request
方法,将其结果转换为Angular $ q promise。 它看起来像这样:
var module = angular.module('example.api', []);
module.factory('api', function(
$q,
$window
) {
function wrappedRequest() {
var result = $window.API.request.apply($window.API, arguments);
return $q.when(result);
};
return {
request: wrappedRequest
};
});
我想编写一个测试,确保此服务正常运行。 它将提供一个带有API
的模拟$window
,其request
方法返回jQuery.Deferred promises。 我需要确保生成的对象是Angular $ q promises。
如何确定对象是否是Angular $ q承诺?
对于这个问题中给出的例子,区分jQuery.Deferred promises和Angular $ q promises就足够了,但理想情况下我们可以识别Angular $ q promises。
通常,更好的方法是将您拥有的任何对象转换为Angular承诺。
吸收可能性的概念是Promises / A +规范的一部分。 大多数承诺库都有办法做到这一点。 它允许在promise实现和统一API之间实现令人敬畏的互操作。
为此,$ q使用.when
:
将一个可能是值的对象或(第三方)包装成$ q承诺。 当您处理可能是或可能不是promise的对象,或者promise是来自不可信任的源时,这非常有用。
它使用了thenables的概念将“不可信”的承诺转换为$ q承诺。
所以你要做的就是
var p = $q.when(value); // p is now always a $q promise
// if it already was one - no harm
作为一个部分解决方案,适用于给定的示例,我们可以通过检查特定方法的存在,轻松区分jQuery.Deferred promises和Angular promise。 例如,Angular的$ q promises有方法catch
来处理错误,而jQuery.Deferred的promises让方法fail
。
function promiseIsAngularOrJQuery(promise) {
if (typeof promise.fail === 'function') {
return 'jquery';
} else if (typeof promise.catch === 'function') {
return 'angular';
} else {
throw new Error("this can't be either type of promise!");
}
}
然而,使用这种技术来区分更多不同类型的承诺,或承诺与非承诺之间,可能会变得非常混乱。 不同的实现经常使用许多相同的方法名称。 它可能会起作用,但我不会走那条路。
有一种替代方案应该能够在合理的条件下可靠地识别$ q promises:在非恶意环境中对可信对象进行操作,只使用单个版本的Angular。 但是,有些人可能认为它太严重,太严重了。
如果使用String()
函数将函数转换为字符串,则结果是该函数的源代码。 我们只需要使用这个来比较.then
方法潜在的承诺对象上.then
已知$ Q承诺对象的方法:
function isAngularPromise(value) {
if (typeof value.then !== 'function') {
return false;
}
var promiseThenSrc = String($q.defer().promise.then);
var valueThenSrc = String(value.then);
return promiseThenSrc === valueThenSrc;
}
我目前的解决方案是使用instanceof
:
var AngularPromise = $q.resolve().constructor;
console.log($q.resolve() instanceof AngularPromise); // true
如果对象确实是Angular Promise,这可以保证返回true。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.