链接Angular承诺拒绝

时间:2014-10-23 17:54:53

标签: javascript angularjs angular-promise angular-translate

我有一个链式承诺,如果拒绝任何一个承诺,我需要执行异步操作(获取翻译的错误消息)。由于我已经获得了成功的链式承诺,我认为它不可能在拒绝时链接 - 我试图简单地嵌套异步调用,但我没有得到解决的承诺从deferred.reject(deferredRejection.promise);下面回来。指针赞赏!

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;
}

更新了解决方案:

根据以下答案,我能够按如下方式重新编写代码:

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被翻译并显示。

1 个答案:

答案 0 :(得分:2)

看起来你并没有真正链接承诺,而是使用the forgotten promise/deferred anti pattern。做一些关于你实际上希望它如何表现的假设,并将对$translate的调用分解出来,那么我怀疑的是以下内容:

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(error)

    上面的所有错误回调都是这样做的。尝试登录或保存后使用翻译密钥作为最终将传递给最终catch回调的错误。来自$translate的成功回调也是为了将其已解决的承诺转换为被拒绝的承诺,因此最终的catch回调返回被拒绝的承诺,因此调用代码获得被拒绝的承诺,并且(可能)显示已转换的错误用户。

  • 如果您肯定想要解决派生的承诺,请返回任何不是成功或错误回调的承诺。派生的承诺将使用该值解决。 (如果您没有明确的返回值,则包括undefined。)

    这是在第一次回调中返回用户return {'accountToken'....时执行的操作。

  • 如果您想推迟解析/拒绝承诺,请从成功或错误回调中返回另一个承诺。然后,派生的承诺最终将以解决/拒绝其他承诺的任何方式得到解决或拒绝。

    这是以上在返回SyncStorageService.write...时以及返回$translate(...时所做的事情。