链接 Angular 承诺拒绝 [英] Chaining Angular promise rejections

查看:21
本文介绍了链接 Angular 承诺拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个链式承诺,如果其中一个承诺被拒绝,我需要执行一个异步操作(获取翻译的错误消息).因为我已经得到了一个关于成功的连锁承诺,我认为不可能也连锁拒绝 - 我试图简单地嵌套异步调用,但我没有从 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.loginSyncStorageService.write 现在都拒绝带有 Error 对象的承诺(例如 new Error('ALERT.ERROR_MESSAGE');),通过 login 冒泡到控制器(之前在服务级别进行翻译);
  • 调用 login 方法的控制器有 .then().catch() 块 - 在 .catch() 上,传递的 Error.message 被翻译和显示.
  • Both AuthService.login and SyncStorageService.write now reject promises with an Error object (e.g. new Error('ALERT.ERROR_MESSAGE');), which bubbles up through login 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 passed Error.message is translated and displayed.

推荐答案

看起来你并没有真正链接 promise,而是使用 遗忘的承诺/延迟的反模式.对您实际希望它的行为方式做出一些假设,并分析出对 $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);
    });
  });
}

要记住的主要事项是:

  • 如果您确实想拒绝派生的 promise,请从成功或错误回调中返回 $q.reject(error).

上面的所有错误回调都是这样做的.尝试登录或保存后的那些使用翻译键作为最终传递给最终 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).

这是上面在第一个回调中返回用户时所做的return {'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(....

This is what's done above when returning SyncStorageService.write..., and when returning $translate(....

这篇关于链接 Angular 承诺拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆