为什么我们更喜欢在角度而不是$ http中使用$ q

时间:2016-06-28 15:19:38

标签: javascript angularjs angular-promise angularjs-http

我目前正在使用来自angular的$ q服务来进行API调用:

var deferred = $q.defer();
$http.get(config.apiHost + details.url)
    .success(function (data) {
        deferred.resolve(data);
    }).error(function (msg) {
        deferred.reject(msg);
    });
return deferred.promise;

但我们也可以在不使用$ q的情况下使用这种方法:

return $http.get(config.apiHost + details.url)
    .success(function (data) {
        return data;
    }).error(function (msg) {
        return msg;
    });

并且当$ http本身返回承诺时,我也可以使用更简化的方法:

$http.get(config.apiHost + 'posts')
        .success(function (data) {
            console.log(data)
        }).error(function (msg) {
            console.log(msg);
        });

所以这些特别是在$ q和$ http之间有什么区别,因为两者都返回promise并且都是异步的? angular是否为$ q提供了一些额外的功能? 我找不到任何好的答案。

3 个答案:

答案 0 :(得分:8)

$http使用$q,第一个例子是多余的,第二个例子也是多余的。您只需要返回$http.get返回的承诺:

return $http.get(config.apiHost + details.url);

以上内容与您的第一段代码相同。

此外,return msgdeferred.reject(msg)不同。等效值为throw msgreturn $q.reject(msg)

需要注意的另一点是,successerror是非标准的,您要使用thencatch

答案 1 :(得分:3)

$q主要仅用于与默认情况下不支持promises的库兼容,以及何时不依赖于Promise的本机实现(例如 - 像IE9这样的老浏览器。除此之外没有理由(为你)使用它。例如,如果您想要基于承诺$timeout。由于这些原因,$http本身使用了$q

与其他(自已删除)答案建议不同,需要使用$q才能存储" $http承诺的结果。我不建议存储承诺(因为这往往导致意大利面条代码),但如果你必须绝对这样做,你可以存储$http的结果承诺;承诺只执行一次。

在承诺解决/拒绝后传递给then的任何函数将在下一个滴答中解决,而不会重新调用创建承诺的原始操作 - IOW,承诺的结果在该对象中被记忆。

还要注意promises链,这个答案的范围超出了范围,但它实质上意味着以下几段代码是等价的

function legacyGet() {
  const deferred = $q.defer()
  $http.get('http://www.google.com')
    .then((response) => deferred.resolve(Object.assign(response, {foo: bar}))
    .catch((error) => deferred.reject(error))
  return deferred.defer
}

function modernGet() {
  return $http.get('http://www.google.com')
    .then((response) => Object.assign(response, {foo: bar}))
}

总结一下:你的头衔错了。我们不喜欢使用$ q,我们只是谨慎使用它。除非您需要支持不具备的浏览器,否则您更喜欢使用ES6 Promise。

答案 2 :(得分:0)

在角度中,大多数服务仅返回promises,但在某些情况下,您希望使用$q创建自己的延迟对象。

案例1

当您使用不支持承诺的库或您已创建自己的函数并希望返回承诺时。

案例2

当你使用任何默认返回一个promise的构造但你想在某些条件下根据某些构造返回一个单独的promise。

示例:在角度$http中仅返回一个承诺但现在如果您希望如果此承诺的响应包含特定值,那么只有您想要返回已解决的其他返回失败然后您需要创建自己的deffered object,并且需要根据$http响应返回的值来解决或失败。