链接Angular承诺拒绝 [英] Chaining Angular promise rejections
问题描述
我有一个链式承诺,如果拒绝任何一个承诺,我需要执行异步操作(获取翻译的错误消息)。由于我已经获得了成功的链式承诺,我认为不可能在拒绝上链接 - 我试图简单地嵌套异步调用,但我没有从获得已解决的承诺deferred.reject(deferredRejection.promise);
如下。指针赞赏!
I have a chained promise and in the case of a rejection for either of the promises, I need to perform an async operation (get the translated error message). As I've already got a chained promise on success, I assume it's not possible to also chain on rejection - I am attempting to simply nest the async calls, but I'm not getting the resolved promise back from deferred.reject(deferredRejection.promise);
below. Pointers appreciated!
login: function(email, password) {
var deferred = $q.defer();
AuthService.login(email, password).then(function(response) {
var user = {
'accountToken': response.accountToken,
'email': response.username,
'onboarded': response.onboarded,
'verified': response.verified
};
return SyncStorageService.write(SyncStorageService.storageKeys.user,
user);
}, function(error) {
// login failed
var deferredRejection = $q.defer();
$translate('ALERTS.LOGIN_FAILED').then(function(translatedValue) {
deferredRejection.resolve(translatedValue);
});
deferred.reject(deferredRejection.promise);
}).then(function(data) {
deferred.resolve(data);
}, function(error) {
// saving data failed
var deferredRejection = $q.defer();
$translate('ALERTS.UNKNOWN').then(function(translatedValue) {
deferredRejection.resolve(translatedValue);
});
deferred.reject(deferredRejection.promise);
});
return deferred.promise;
}
更新解决方案:
根据以下答案,我能够按如下方式重新编写代码:
Based on the answer below, I was able to re-write the code as follows:
login: function(email, password) {
return AuthService.login(email, password).then(function(response) {
return {
'accountToken': response.accountToken,
'email': response.username,
'onboarded': response.onboarded,
'verified': response.verified
};
}).then(function(data) {
return SyncStorageService.write(SyncStorageService.storageKeys.user,
data);
});
}
注意:
- 两者
AuthService.login
和SyncStorageService.write
现在以<$ c拒绝承诺$ c>错误对象(例如新错误('ALERT.ERROR_MESSAGE');
),通过登录冒泡
到控制器(以前在服务级别进行翻译); - 调用
登录的控制器
方法有.then()
和.catch()
blocks - 在.catch()上,传递翻译并显示Error.message
。
- Both
AuthService.login
andSyncStorageService.write
now reject promises with anError
object (e.g.new Error('ALERT.ERROR_MESSAGE');
), which bubbles up throughlogin
to the controller (previously was doing the translation at the service level); - The controller that calls the
login
method has.then()
and.catch()
blocks - on a .catch(), the passedError.message
is translated and displayed.
推荐答案
看起来你并没有真正链接承诺,并使用被遗忘的承诺/延迟反模式。做一些关于你实际上想要它的行为的假设,并将对 $ translate
的调用分解出来,那么我怀疑的是你所追求的东西:
It looks like you're not really chaining promises, and using the forgotten promise/deferred anti pattern. Making a few assumptions about how you actually want it to behave, and factoring out the calls to $translate
, then something like the following I suspect is what you're after:
login: function(email, password) {
return AuthService.login(email, password).then(function(response) {
return {
'accountToken': response.accountToken,
'email': response.username,
'onboarded': response.onboarded,
'verified': response.verified
};
}, function() {
return $q.reject('ALERTS.LOGIN_FAILED');
}).then(function(user) {
return SyncStorageService.write(SyncStorageService.storageKeys.user, user).catch(function() {
return $q.reject('ALERTS.UNKNOWN');
});
}).catch(function(message) {
return $translate(message).then(function(translatedValue) {
return $q.reject(translatedValue);
});
});
}
要记住的主要事项是:
-
如果您肯定要拒绝派生的承诺,请从
$ q.reject(错误)
返回成功或错误回调。
If you definitely want to reject the derived promise, return
$q.reject(error)
from the success or error callback.
上面的所有错误回调都是这样做的。尝试登录或保存后使用翻译密钥作为错误,最终将传递给最终的 catch
回调。来自 $ translate
的成功回调也会将其解析后的承诺转换为被拒绝的承诺,因此最终的catch回调会返回被拒绝的承诺,因此调用代码会被拒绝承诺,并且(可能)向用户显示已翻译的错误。
All the error callbacks above do this. The ones after attempted login or saving use the translation key as the error that will be eventually passed to the final catch
callback. The success callback from $translate
also does this to transform its resolved promise to a rejected one, so the final catch callback returns a rejected promise, so the calling code gets a rejected promise, and (presumably) shows the translated error to the user.
如果您肯定想要解决派生的承诺,请返回任何非承诺的内容他成功或错误回调。派生的承诺将使用该值解决。 (如果你没有明确的返回值,这包括 undefined
。)
If you definitely want to resolve the derived promise, return anything that isn't a promise from he success or error callbacks. The derived promise will be resolved with that value. (This includes undefined
if you don't have an explicit return value).
这是上面所做的返回用户在第一次回调中返回{'accountToken'....
。
This is what is done above when returning the user return {'accountToken'....
in the first callback.
如果你想推迟解决/拒绝承诺,从成功或错误回调中返回另一个承诺。然后,派生的承诺最终将以解决/拒绝其他承诺的任何方式得到解决或拒绝。
If you want to defer the resolution/rejection of a promise, return another promise from the success or error callback. Then the derived promise will be eventually resolved or rejected in whatever manner this other promise is resolved/rejected.
这是返回 SyncStorageService时的做法.write ...
,当返回 $ translate(...
。
这篇关于链接Angular承诺拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!