为什么我们更喜欢在 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 msg
与deferred.reject(msg)
不一样。等价于 throw msg
或 return $q.reject(msg)
另外需要注意的是success
和error
是非标准的,你要用then
和catch
。
$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
响应。
我目前正在使用 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 msg
与deferred.reject(msg)
不一样。等价于 throw msg
或 return $q.reject(msg)
另外需要注意的是success
和error
是非标准的,你要用then
和catch
。
$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
响应。