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

Bhu*_*oel 13 javascript angularjs angularjs-http angular-promise

我目前正在使用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;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

elc*_*nrs 8

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

return $http.get(config.apiHost + details.url);
Run Code Online (Sandbox Code Playgroud)

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

另外,return msg是不一样的deferred.reject(msg).相当于throw msgreturn $q.reject(msg)

另一件需要注意的事情是,success并且error是非标准的,你想使用thencatch.


Dan*_*try 4

$q主要仅用于与默认情况下不支持 Promise 的库兼容,以及当您不能依赖其本机实现时Promise(例如 - 在 IE9 等较旧的浏览器中)。没有理由(对你来说)以其他方式使用它。如果您想做出基于承诺的$timeout. 由于这些确切的原因,它本身在幕后$http使用。$q

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

Promise 已解决/拒绝后传递给的任何函数then都将在下一个tick 时得到解决,而无需重新调用最初创建 Promise 的原始操作 - IOW,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}))
}
Run Code Online (Sandbox Code Playgroud)

总结一下:你的标题是错误的。我们不喜欢使用 $q,我们只是很少使用它。优先使用 ES6 Promise,除非您需要支持没有它的浏览器并且您无法使用 polyfill。