Angular2等待$http响应

3

我几乎所有的REST请求都需要用户ID。

当我登录一个用户时,我会将token传递到本地存储,并将ID传递给user.service.ts(通过函数setUserId(userId);)。但是当我仅通过令牌进行用户身份验证(用户已登录但页面已刷新),我尝试从User对象中获取userID(通过token从REST请求中获取用户对象)。

我的代码的这部分看起来像:

getUser() {
    var authToken = localStorage.getItem('authorization')

    if(!this.userPromise){
      let headers = new Headers();
      headers.append('Content-type', 'application/json');
      headers.append('Authorization', authToken);

      this.userPromise = this.http.get(
        'http://localhost:8080/api/user',
        { headers }
      ).toPromise()
        .then((res) => res.json());
    }

    return this.userPromise;
  };




getUserId(){
    var $self = this;

    if($self.userId){
      return $self.userId;
    } else {
      $self.getUser().then(function(result){
        $self.setUserId(result.id);
        console.log(result.id);
        return result.id;
      });
    }
  }

当任何请求要求用户ID时,我使用getUserId()函数并检查用户ID是否已定义。如果已定义,则响应此数据,但如果未定义,则希望从getUser()函数中获取此数据。
我无法解决一个问题 - 此请求是异步的,例如“任务”服务将userId值设置为未定义 - 不等待此新值。
如何解决这个问题?
---编辑
这里有一个请求 - 它不等待响应;
 getUserTasks() {
    // return this.userService.getUserId();
    var userId = this.userService.getUserId();

    return this.http.get(
      'http://localhost:8080/api/private/'+userId+'/tasks'
      // 'http://localhost:8080/api/private/1/tasks'
    )
    .toPromise()
      .then((res) => res.json());
  }

请问您能提供一个 Plnker 吗? - SeleM
你能展示一下在模板中如何使用这个值吗?这样我才能告诉你最快的实现方式。你似乎为一个小任务付出了太多的努力。 - Omri Luzon
在我的模板中,我只有这个: {{data | async}}我知道 - 我可以使用ng-if =“user.id”在框架中加载所有内容,但在这种情况下,这不是一个好的解决方案。 - kris_IV
如果你使用箭头函数 () => {} 而不是 function() {},那么你就不需要使用丑陋的 $self hack,而可以直接使用 this. - Günter Zöchbauer
感谢@GünterZöchbauer的建议。有时候我会忘记在ES6中使用它,因为我经常在旧标准下编码,那里需要这个。 - kris_IV
1个回答

4

我找到了解决方案 - 唯一需要做的是在getUserTasks()函数上正确使用async/await功能:

 async getUserTasks() {
    let userId = await this.userService.getUserId();

    return this.http.get(
      'http://localhost:8080/api/private/'+userId+'/tasks'
    )
    .toPromise()
    .then((res) => res.json());
  }

---编辑---

最后,如果有人遇到相同的问题,我将我的更改提升到认证过程。这样,通过服务UserService.getUserId(),我可以从应用程序的任何部分访问userId。

当用户登录时,我有时间将所有数据放入变量中,但是当我只进行身份验证时,我将修改isLoggedIn()函数为异步/等待。如果票证存在,我会发送身份验证请求以获取用户对象。

如果我得到用户对象,我将返回true并将userId放入userId服务。当我收到错误(没有凭据)时,我在getUser()函数中执行注销操作。

我认为这是最好的解决方案-它提供了所有必要的数据,并在保护器中提供了额外的验证过程。

async isLoggedIn() {
    var $self = this;

    if(localStorage.getItem("authorization")){
      var user = await $self.getUser();
      this.setUserId(user.id);

      return true;
    } else {
      return false;
    }
  }

1
很高兴听到这个消息,只是想让你知道,在幕后,async/await使用了Promise。如果你想更多地了解它,请点击这里阅读一篇好的文章。 - Omri Luzon
谢谢你的帮助,@Omri Luzon。 - kris_IV

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