我已经阅读了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
},
答案 0 :(得分:2)
var deferred = $q.defer(); //Why am I doing this?
这是你正在做的deferred anti-pattern,因为你不了解承诺。在应用程序逻辑中使用$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;
}
}
答案 1 :(得分:1)
promise是一个不立即执行的函数。相反,你有希望'在完成它的处理时响应延迟对象的状态。实质上,您正在创建一个模拟多个线程的执行链。一旦延迟对象完成,它就会返回一个状态代码,调用函数能够响应状态代码,并在必要时返回它自己的状态代码等。
var deferred = $q.defer();
在这里,您要创建一个延迟对象,以保存稍后将执行的回调。
var promise = auth.$changePassword(email, oldPassword, newPassword);
这是实际的功能,但你不是在这里调用它。您正在创建一个变量来引用它,以便您可以监视它。
var rValue = promise.then(function(){
.then()是承诺成功时将执行的函数。在这里,您将概述一项功能,该功能将在承诺工作成功后执行。
}, function(error){
然后链接错误函数,如果promise失败则执行该错误函数。除了返回错误代码之外,你实际上并没有做任何事情,但你可以自己做一些事情来回应失败。
deferred.resolve(promise);
这是您实际告诉延迟对象执行代码,等待结果,然后根据需要执行成功或失败代码的点。承诺被添加到执行链中,但您的代码现在可以自由继续,无需等待和挂起。一旦承诺完成并处理成功或失败,您的一个回调函数将处理。
console.log(rValue);
您的函数未返回此处的实际值,因为您不希望函数在继续之前停止并等待响应,因为这会阻止程序直到函数完成。
return rValue;
您正在向呼叫者回复您的承诺。你的函数是一个承诺,它调用一个可能正在调用另一个promise等的promise,如果你的函数不是一个promise,那么即使你调用的代码没有阻塞,你的代码也会在你等待的时候成为一个块。执行完成。通过将承诺链接在一起,您可以定义如何在没有响应的情况下做出响应。您没有直接返回结果,而是承诺'返回成功或失败,在这种情况下,通过您正在调用的函数成功或失败。
答案 2 :(得分:1)
你所做的是混合的承诺。当你输入代码注释时,
angularfire中的$ changepassword返回一个承诺
基本上,var deferred = $q.defer()
使用deferred.promise
创建新承诺,但您已经使用$changePassword
创建了承诺。如果我理解你正在尝试做什么,你只需要这样做。
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
});
}]);
答案 3 :(得分:1)
当您要执行将花费不明时间的任务时,或者在完成任务时您并不关心 - 异步任务时,您使用延期承诺。所有你关心的是,只要你所调用的代码告诉你任务完成,就会得到一个结果。
您在函数中应该做的是返回您正在创建的延迟的承诺。您调用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
}