返回承诺里面的解析函数作为它的延续

时间:2016-12-28 17:01:22

标签: javascript angularjs asynchronous

上下文

我正在与Angular合作。我有一个名为 UserService 服务,用于处理登录,身份验证和用户数据请求。

get 方法需要在发出get请求之前检查用户是否具有有效(未过期)的身份验证令牌。 因此,如果有,请提出请求,如果没有请求令牌,然后发出请求。

问题

get 方法需要隐藏其复杂请求。它必须只返回一个Promise,因为它只发出一个请求。

所以,一个用法的例子:

UserService
    .get()
    .then(data => { ... })
    .catch(error => { ... })

错误的解决方案

检查令牌是否已过期。如果是,则返回刷新令牌的请求,然后生成并返回get请求。如果不是,只需创建并返回get请求。如下:

function get() {
    if (isTokenExpired(token))
        return $http
            .post(url + '/refreshtoken', 'token=' + refreshToken)
            .then(response => {
                token = response.data.token
                return $http.get(url + '?token=' + token)
            })
            .catch(response => { ... })
    else
        return $http.get(url + '?token=' + token)
}

但它正在回复我必须处理的承诺:

UserService
    .get()
    .then(request => {
        request // THAT IS NOT GOOD
            .then(data => { ... })
            .catch(error => { ... })
    })
    .catch(error => { ... })

像使用示例一样!

正确的解决方案

如何在服务上创建 get 方法,该方法处理这样的身份验证并隐藏将要使用的控制器中的所有内容,让它在用法示例中使用?

2 个答案:

答案 0 :(得分:3)

  

但它已经答应了我必须要处理的承诺:

 UserService.get().then(request => { request.then(data => { … }) })

Promises do chain,任何"承诺承诺"将隐含地扁平化为对内在结果的承诺。你的错误解决方案"代码只是按原样运行。

答案 1 :(得分:0)

这是一个例子。基本上你需要使用额外的.then()

进行转换

angular.module('app', [])
  .service('UserService', function($http) {
    let url = 'https://jsonplaceholder.typicode.com';

    function getUserData(token) {
      return $http.get(url + '/users/1', {
          token: token
        })
        .then(resp => resp.data);
    }

    this.get = function(tokenIsValid) {
      if (!tokenIsValid){
        console.log('refreshing');
        return $http.post(url + '/posts', {
            refreshToken: 'rt'
          })
          .then(getUserData)
        }
      return getUserData();
    }
    return this;
  })
  .run(function($rootScope, UserService) {
    $rootScope.get = (valid) => {
      console.log('Getting with ' + (valid? '':'in') + 'valid token');
      UserService.get(valid)
        .then(console.log)
        .catch(console.error);
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <button ng-click="get()">Get invalid</button>
  <button ng-click="get(true)">Get valid</button>
</div>