【问题标题】:Why is a $q promise returning an $http promise as a payload?为什么 $q 承诺会返回 $http 承诺作为有效负载?
【发布时间】:2014-07-31 20:52:55
【问题描述】:

我有一个承诺链,它必须在链的中途调用$http,并将生成的承诺传递给下一个处理程序。问题是我的 .then() 成功函数似乎将返回的 $http 承诺包装在另一个承诺中,导致我的 http 承诺被视为有效负载。因此,当它在链中的下一个链接中解析时,我得到的是一个承诺,而不是 http 响应。

var statusPromise = Auth.getUserStatus();

var tokenPromise = statusPromise.then(function(status) {
    if (status && status.accesstoken) {
        return status.accesstoken;
    } else {
        return null;
    }
});

var httpPromise = tokenPromise.then(function(accesstoken) {
    console.log('access token', accesstoken);
    var params = {
        page: page,
        limit: limit
    };

    if (accesstoken) {
        params.accesstoken = accesstoken;
    }

    return $http.get(apiUrl + 'scenes/' + filter + '/', {
        data: $.param(params),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    });
});

var doMoreStuffPromise = httpPromise.then(function(response) {
    console.log(response); // this logs the promise as the payload, not the http response
    return response.data;
});

return doMoreStuffPromise;

如何在我的链中链接$http 承诺?

【问题讨论】:

    标签: angularjs promise angular-services


    【解决方案1】:

    $http 调用返回承诺,并且承诺递归同化......问题不在于承诺。问题出在$http API 上。事实上,对于像 $q 这样的 Promises/A+ 实现来说,在不解包的情况下返回 thenable 是完全不可能的。

    如果你使用.then(在成功的情况下)它的行为方式与你使用.success不同,除了.success没有链接,它resolves with .data

    您的代码也应该这样做:

    var doMoreStuffPromise = httpPromise.then(function(rep) {
        console.log(resp.data);  // now, your actual data
        return resp.data;
    });
    

    【讨论】:

    • 这就是我所做的,在我的例子中,我刚刚将要传递的回调变量命名为data。如果我按照你的建议去做,resp 仍然是一个被之前的tokenPromise.then() 包装的承诺。一个 Promise 作为另一个 Promise 中的有效负载。
    • 我还更新了我的问题中的代码,以便用不那么含糊的命名法更清楚地说明这一点。
    • 我赞成这个答案,因为您对 Promises/A+ 实现的评论比我认为的更正确。 JQuery 承诺不是 A+ 并且不会解包,因此看起来非常相似,但被包装了。
    【解决方案2】:

    我发现了这个问题。它发生在链条的上游,比我预期的要远得多。原来我的 Auth 服务有一个 bug:

    this.getUserStatus = function() {
        $.when(...); // woops, no $q
    };
    

    应该是:

    this.getUserStatus = function() {
        $q.when(...);
    };
    

    我不小心忘记了$q,因为$.when() 是一个用于创建promise 的合法jQuery 函数,所以没有什么会彻底失败。但是,由于 Angular 和 jquery 承诺的工作方式略有不同,因此一个包装另一个而不是展开。

    【讨论】:

    • 有趣。我从来没有在野外看到过这个问题,并且认为它纯粹是理论上的:-)
    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多