繁体   English   中英

如何判断对象是否是Angular $ q承诺?

[英]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。

演示: https//jsfiddle.net/DerekL/cmzp7ovj/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM