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

查看:116
本文介绍了链接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.login SyncStorageService.write 现在以<$ c拒绝承诺$ c>错误对象(例如新错误('ALERT.ERROR_MESSAGE'); ),通过登录冒泡到控制器(以前在服务级别进行翻译);

  • 调用登录的控制器方法有 .then() .catch() blocks - 在.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.

推荐答案

看起来你并没有真正链接承诺,并使用被遗忘的承诺/延迟反模式。做一些关于你实际上想要它的行为的假设,并将对 $ 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屋!

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