对$q和承诺的困惑
Confusion about $q and promises
我已经读了几个小时Kris Kowal的Q和angularjs$Q变量了。但就我的一生而言,我不知道这是怎么回事。
目前,我的服务中有以下代码:
resetpassword: function (email, oldPassword, newPassword) {
var deferred = $q.defer(); //Why am I doing this?
var promise = auth.$changePassword(email, oldPassword, newPassword); //$changepassword in angularfire returns a promise
console.log(deferred); //Object with resolve, reject, notify and promise attrs
var rValue = promise.then(function(){
//successcallback
return 1; //if changepassword succeeds it goes here as expected
}, function(error){
//errorcallback
return error.code; //if changepassword fails (wrong oldpass for example) it goes here, also works
}
);
deferred.resolve(promise); //Should I do this? I thought my promise was resolved in the callbacks?
console.log(rValue); //This outputs another promise? Why not 1 or error.code, how the am I ever going to get these values??
return rValue; //I want 1 or error.code to go back to my controller
},
var deferred = $q.defer(); //Why am I doing this?
这是你所做的延迟反模式,因为你不理解承诺。实际上,在应用程序逻辑中使用$q.defer()
从来都不是一个好的理由。
你需要从你的功能返回一个承诺:
resetpassword: function(email, oldPassword, newPassword) {
return auth.$changePassword(email, oldPassword, newPassword)
.then(function() { return 1; })
.catch(function(e) { return e.code });
}
用法是:
resetpassword(...)
.then(function(num) {
if (num === 1) {
}
else {
}
});
这有助于思考如何用同步代码编写函数:
resetpassword: function(email, oldPassword, newPassword) {
try {
auth.$changePassword(email, oldPassword, newPassword)
return 1;
}
catch (e) {
return e.code;
}
}
promise是一个不会立即执行的函数。相反,您"承诺"在延迟对象完成处理时对其状态作出响应。从本质上讲,您正在创建一个模拟多个线程的执行链。一旦一个延迟对象完成,它就会返回一个状态代码,调用函数能够响应状态代码,并在必要时返回自己的状态代码,等等
var deferred = $q.defer();
在这里,您正在创建一个延迟对象,以保存稍后将执行的回调。
var promise = auth.$changePassword(email, oldPassword, newPassword);
这是实际的函数,但您不是在这里调用它。你正在制作一个变量来引用它,这样你就可以监视它
var rValue = promise.then(function(){
.then((是在promise成功时将执行的函数。在这里,您正在内联一个函数,该函数将在promise的工作成功后执行。
}, function(error){
然后链接错误函数,如果promise失败,将执行该函数。除了返回错误代码之外,您实际上没有在这里做任何事情,但您可以自己做一些事情来响应失败。
deferred.resolve(promise);
这就是您实际告诉延迟对象执行代码,等待结果,然后根据情况执行成功或失败代码的地方。promise被添加到执行链中,但您的代码现在可以自由地继续,而无需等待和挂断。一旦promise完成并处理成功或失败,您的一个回调函数就会进行处理。
console.log(rValue);
您的函数不会在此处返回实际值,因为您不希望函数在继续之前停止并等待响应,因为这会阻塞程序,直到函数完成。
return rValue;
你是在向来电者回报你的承诺。你的函数是一个promise,它正在调用一个可能正在调用另一个promet的promise,等等。如果你的函数不是promise,那么即使你正在调用的代码没有被阻塞,当你等待执行完成时,你的代码也会变成一个块。通过将承诺链接在一起,你可以定义你应该如何回应,而不必在那一刻做出回应。您不是直接返回结果,而是"承诺"返回成功或失败,在这种情况下,通过您正在调用的函数传递成功或失败。
当您要执行一项将花费未知时间的任务时,或者您不在乎它何时完成时,您会使用延迟承诺-异步任务。只要您调用的代码告诉您任务已完成,您所关心的就是返回结果。
在您的函数中,您应该做的是返回您正在创建的递延的承诺。调用resetpassword
的代码应该等待这个承诺得到解决。
function (email, oldPassword, newPassword) {
var deferred = $q.defer(); //You are doing this to tell your calling code when the $changepassword is done. You could also return the promise directly from angularfire if you like but of course the return values would be different.
var promise = auth.$changePassword(email, oldPassword, newPassword); //$changepassword in angularfire returns a promise
console.log(deferred); //Object with resolve, reject, notify and promise attrs
promise.then(function(){
//successcallback
deferred.resolve(1); //if changepassword succeeds it goes here as expected
}, function(error){
//errorcallback
deferred.reject(0); //if changepassword fails (wrong oldpass for example) it goes here, also works
}
);
// Quite right, you should not do this.
console.log(rValue); //This outputs another promise? Why not 1 or error.code, how the am I ever going to get these values??
return deferred.promise; // Return the promise to your controller
}
您所做的是混合承诺。正如你在代码注释中所说,
angularfire中的$changepassword返回一个承诺
基本上,var deferred = $q.defer()
使用deferred.promise
创建了一个新的promise,但您已经在使用$changePassword
创建promise了。如果我理解你试图正确地做什么,你只需要这样做。
resetpassword: function (email, oldPassword, newPassword) {
auth.$changePassword(email, oldPassword, newPassword).then(function(result) {
console.log(result); // success here
}, function(err){
console.log(err); // error here
});
}
编辑:
根据Robins的评论,如果您想在控制器中处理结果,而不是在服务中调用then()
函数,请将promise本身返回给控制器。这里有一个例子:
服务功能:
resetpassword: function (email, oldPassword, newPassword) {
// return the promise to the caller
return auth.$changePassword(email, oldPassword, newPassword);
}
控制器功能:
.controller('MyCtrl', ['$scope', 'myService', function($scope, myService){
// get the promise from the service
myService.resetPassword($scope.email, $scope.oldPassword, $scope.newPassword).then(function(result){
// use 1 here
}, function(err){
// use err here
});
}]);
- 我的职位回报太快了,如何做出承诺
- 打破承诺链的好方法是什么
- 从函数返回角度承诺
- 我怎样才能获得承诺的价值
- 延期承诺值未更新/解析/延期
- 在承诺链中处理早期回报的最佳方式
- 承诺在非节点式回调上使用Bluebird
- 简单的ES6承诺问题-交换解决和拒绝参数
- 组合承诺和非承诺值
- 带有对象/原型的链式承诺(Q延期)
- AngularJS$q承诺使用socket.io
- React JS:未捕获(在承诺中)语法错误:在位置 0 的 JSON 中意外<令牌
- 当一些承诺失败时,如何继续使用$q.all()
- Nodejs和express路由,如何处理客户端的承诺
- 如何在多承诺链中处理谷歌地图API V3事件
- 承诺合并流
- JavaScript承诺-无法读取属性'那么'的未定义
- 等待循环调用的所有承诺完成
- Pg承诺性能提升:在冲突中
- 如何判断请求/承诺是否需要超过5秒才能完成,angular js