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

Why do we prefer using $q in angular instead of $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本身returns的承诺,我也可以使用更简化的方法:

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

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

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

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

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

此外,return msgdeferred.reject(msg)不一样。等价于 throw msgreturn $q.reject(msg)

另外需要注意的是successerror是非标准的,你要用thencatch

$q 主要仅用于与默认情况下不支持承诺的库兼容,以及当您不能依赖 Promise 的本机实现时(例如 - 在旧浏览器中像 IE9)。没有理由(对您而言)以其他方式使用它。如果你想制作一个 promise-based $timeout,就是一个例子。由于这些确切原因,$http 本身在幕后使用 $q

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

在承诺 resolved/rejected 之后传递给 then 的任何函数都将在下一个 tick 时解决,没有 re-invoking 首先创建承诺的原始操作 - IOW , promise 的结果被记录在 object.

还要注意 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,除非你需要支持没有它的浏览器并且你不能使用 polyfill。

在 angular 中,大多数服务仅 return 承诺,但在某些情况下,您希望使用 $q.[=14= 创建您自己的延迟对象]

案例一

当您使用不支持 promise 的库或者您已经创建了自己的函数并想要 return 一个 promise。

案例二

当您使用任何默认 return 承诺但您想 return 基于某些条件的单独承诺时。

示例:在 angular $http return 中只是一个承诺,但是现在如果你想要这个承诺的响应包含一个特定值那么只有你想 return 解决 else return 失败然后你需要创建自己的 deffered object 并且需要根据 returned 的值解决它或使它失败$http 响应。