te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - How can I tell if an object is an Angular $q promise? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I tell if an object is an Angular $q promise? - Stack Overflow

programmeradmin4浏览0评论

I have a pre-existing non-Angular API library in my project. It has a .request method which returns jQuery.Deferred promises. I created a simple Angular service which wraps the .request method to transform its result into an Angular $q promise instead. It looks something like this:

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
    };
});

I would like to write a test which ensures that this service is functioning correctly. It will provide a mock $window with an API whose request method returns jQuery.Deferred promises. I need to ensure that the resulting objects are Angular $q promises.


How can I determine whether an object is an Angular $q promise?

For the example given in this question it would be sufficient to distinguish between jQuery.Deferred promises and Angular $q promises, but ideally we could identify Angular $q promises in general.

I have a pre-existing non-Angular API library in my project. It has a .request method which returns jQuery.Deferred promises. I created a simple Angular service which wraps the .request method to transform its result into an Angular $q promise instead. It looks something like this:

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
    };
});

I would like to write a test which ensures that this service is functioning correctly. It will provide a mock $window with an API whose request method returns jQuery.Deferred promises. I need to ensure that the resulting objects are Angular $q promises.


How can I determine whether an object is an Angular $q promise?

For the example given in this question it would be sufficient to distinguish between jQuery.Deferred promises and Angular $q promises, but ideally we could identify Angular $q promises in general.

Share Improve this question asked Mar 20, 2014 at 21:57 Jeremy Banks - Vive le CanadaJeremy Banks - Vive le Canada 130k88 gold badges358 silver badges381 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

Generally the better approach is to cast whatever object you do have into an Angular promise.

The concept of assimilating thenables is part of the Promises/A+ specification. Most promise libraries have a way to do this. It's what allows for awesome interop between promise implementations and a uniform API.

For this, $q uses .when :

Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise es from a source that can't be trusted.

It uses the concept of thenables to convert a 'non trusted' promise into a $q promise.

So all you have to do is

var p = $q.when(value); // p is now always a $q promise
                        // if it already was one - no harm

As a partial solution, adequate and appropriate for the given example, we can easily distinguish between jQuery.Deferred promises and Angular promises by checking for the presence of specific methods. For instance, Angular's $q promises have the method catch to handle errors, while jQuery.Deferred's promises have the method 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!");
    }
}

However, using this technique to distinguish between more different types of promises, or between promises and non-promises, could get very messy. Different implementations often use use many of the same method names. It could probably be made to work, but I'm not going down that road.


There is an alternative that should be able to reliably identify $q promises under reasonable conditions: operating on trusted objects in a non-hostile environment, with only a single version of Angular in use. However, some might see it as too "hacky" for serious use.

If you convert a function to a string using the String() function, the result is the source code for that function. We just need to use this to pare the .then method on a potential promise object to the .then method of a known $q promise object:

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;
}

My current solution is to use instanceof:

var AngularPromise = $q.resolve().constructor;

console.log($q.resolve() instanceof AngularPromise);  // true

This guarantees to return true iff the object is indeed an Angular Promise.

Demo: https://jsfiddle/DerekL/cmzp7ovj/

发布评论

评论列表(0)

  1. 暂无评论