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

Why do we prefer using $q in angular instead of $http

本文关键字:http 更喜欢 我们 angular 为什么      更新时间:2023-09-26

我目前正在使用$q service从angular发出这样的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提供了一些额外的功能?我找不到一个好的答案

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

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

上面的代码与你的第一段代码相同。

此外,return msgdeferred.reject(msg)不相同。相当于throw msgreturn $q.reject(msg)

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

$q主要用于兼容默认情况下不支持承诺的库,以及当您无法依赖Promise的本机实现时(例如在IE9等较旧的浏览器中)。(你)没有理由不这样用它。一个例子,如果你想做一个基于承诺的$timeout$http本身使用$q正是出于这些原因。

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

在promise被解析/拒绝后传递给then的任何函数都将在下一个tick被解析,而不需要重新调用最初创建promise的原始操作-因此,promise的结果将在该对象中被记忆。

还要注意承诺链,它有点超出了这个答案的范围,但它实际上意味着以下代码片段是等效的
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,除非你需要支持不支持它的浏览器你不能使用polyfill

在angular中,几乎所有的服务都只返回承诺,但在某些情况下,你想使用$q创建自己的延迟对象。

案例1

当你使用的库不支持promise,或者你创建了自己的函数,想要返回promise时,

案例2

当你使用任何默认返回承诺的结构,但你想在某些条件下返回一个单独的承诺时,

示例:在angular中,$http只返回一个promise,但现在如果你想这样做,如果这个promise的响应包含一个特定的值,那么只有你想返回resolved否则返回failure,那么你需要创建自己的deffered object,并需要根据$http响应返回的值来解析或失败。