我目前正在使用来自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提供了一些额外的功能? 我找不到任何好的答案。
答案 0 :(得分:8)
$http
使用$q
,第一个例子是多余的,第二个例子也是多余的。您只需要返回$http.get
返回的承诺:
return $http.get(config.apiHost + details.url);
以上内容与您的第一段代码相同。
此外,return msg
与deferred.reject(msg)
不同。等效值为throw msg
或return $q.reject(msg)
需要注意的另一点是,success
和error
是非标准的,您要使用then
和catch
。
答案 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
响应返回的值来解决或失败。