AngularJS:如何在.then中返回一个Promise?

5
我有一个用户服务。我想创建一个方法,利用我已经构建的另一个服务。该服务有两个方法:getUser()getCurrentUser()getCurrentUser()使用注入的服务来获取UID。它使用返回的UID来运行getUser()方法。我的问题是,我无法让getCurrentUser()返回第二层承诺。
这个问题有点难以解释。以下是代码...
svs.service("usersService", function($rootScope, $http, loginService, alertBoxService) {
  var self = this;
  self.getUser = function(identifier, column) {
    if (typeof(column) === 'undefined') column = "uid";
    return $http.get($rootScope.api + "/getUser/" + identifier + "/" + column);
  }
  self.getCurrentUser = function() {
    var currentUserPromise;
    loginService.getCurrentUid().then(
      function(response) {
        if (response.data === "false") {
          alertBoxService.trigger($rootScope.unexpectedApiResponse);
        } else {
          console.log(self.getUser(response.data));
          currentUserPromise = self.getUser(response.data);
        }
      }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
      }
    );
    return currentUserPromise;
  }
});

当然可以。但是你根本不需要那个变量! - Bergi
3个回答

4

将 Promise 连锁在一起,但不要忘记连锁拒绝(rejections)...

self.getCurrentUser = function() {
    return loginService.getCurrentUid().then(function(response) {
        if (response.data === 'false') {
            alertBoxService.trigger($rootScope.unexpectedApiResponse);
            return $q.reject(response); // convert into a rejection
        }
        return self.getUser(response.data); // chain the promise resolution
    }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
        return $q.reject(response); // chain the rejections
    });
}

当然,您需要注入$q服务。


正如Bergi所指出的那样,您也可以通过抛出错误而不是使用$q.reject来拒绝承诺,例如:

throw response;

你可能会想要突出显示第一个添加的return,因为对于学习then的人来说很容易被遗漏。 - Bergi
我们在这里对 $q 做什么? - Allenph
1
你可以使用throw来抛出错误,而不是使用$q.reject - Bergi
@Bergi 哦,是的,我忘了那个。但这不会是重新抛出,因为没有什么被捕获 ;) - Phil
2
@Allenph 当使用 thencatch 的第二个参数处理 Promise 拒绝时,它会被转换为已解决的 Promise,除非该处理程序返回一个拒绝的 Promise 或抛出错误。这使得上游消费者知道 Promise 被拒绝了。否则,他们会认为它是成功的。 - Phil
1
@Allenph ...并且使用undefined作为完成值仍然能够成功,但这可能是意料之外的,会导致后续异常。 - Bergi

0
这里的问题是当调用函数getCurrentUser时,它立即返回一个undefined变量。这是因为服务是异步的,当服务接收到响应时,函数调用已经返回了一个undefined变量。为了防止这种情况,您可以在loginService中添加return调用。

0

对于异步函数来说,如果要从成功回调中返回一个 Promise,你需要从回调中返回 Promise 对象,然后从主函数中返回以提供 Promise 给调用者。

试试这个。

  svs.service("usersService", function($rootScope, $http, loginService, alertBoxService) {
  var self = this;
  self.getUser = function(identifier, column) {
    if (typeof(column) === 'undefined') column = "uid";
    return $http.get($rootScope.api + "/getUser/" + identifier + "/" + column);
  }
  self.getCurrentUser = function() {
    return loginService.getCurrentUid().then(
      function(response) {
        if (response.data === "false") {
          alertBoxService.trigger($rootScope.unexpectedApiResponse);
        } else {
          console.log(self.getUser(response.data));
          return self.getUser(response.data);
        }
      }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
      }
    );
  }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接