【问题标题】:Executing a http request based the result of a previous request in angular 2根据 Angular 2 中先前请求的结果执行 http 请求
【发布时间】:2025-12-08 21:30:01
【问题描述】:

我想在 Angular 2 中使用 Observable 时处理异步流。 具体来说,在每个用户的请求之前,我需要获取服务票,如果该票有效,用户可以得到适当的响应。因此,我必须在实际请求之前先进行http请求,如下所示,我调用了getServiceTicket()方法,但是由于异步流,在我获得有效的服务票证之前,没有执行以下http请求(getDetail)有效的服务票。所以我尝试使用像isServiceTicket这样的标志,但我意识到它并不能保证这两种方法的顺序运行。我试图做一些研究,但我找不到满意的答案。如果有人对此有很好的解决方案,您能给一些建议吗?

getServiceTicket() {
    this.userAuthServie.getServiceTicket().subscribe(
        (data: string) => {this.serviceTicket = data; this.isServiceTicket = true;}
    );
}

getDetail(id: string) { 
    this.getServiceTicket();
    return this.http.get('https://localhost/detail/' + id + '?ticket=' + this.serviceTicket)
    .map( (responseData) => {
        return <User>responseData.json();
    }
    );
}

【问题讨论】:

标签: http angular request observable


【解决方案1】:

您可以像下面这样更改您的代码:

user:User;

      getDetail(id: string) {

        this.userAuthServie.getServiceTicket()
          .subscribe((data: string) => {
            this.serviceTicket = data;
            this.isServiceTicket = true;
            this.http.get('https://localhost/detail/' + id + '?ticket=' + this.serviceTicket)
              .map( (responseData) => {
                this.user= <User>responseData.json();
              });
          });

      }

【讨论】:

  • 如果我这样做,我会得到“无法读取未定义的属性'订阅'”。
  • 在UserAuthService中提供代码getServiceTicket
  • 非常感谢。以下是来自 UserAuthService 的 getServiceTicket。 getServiceTicket() { 让 cuser = JSON.parse(localStorage.getItem('cUser'));让 creds = "servicename=xxx.xxx.xxx";让标头=新标头(); headers.append('Content-Type', 'application/x-www-form-urlencoded'); if(cuser.token) { return this.http.post('localhost/serviceTicket' + cuser.token + '?serviceName=xxx.xxx.xxx', creds, { headers: headers }) .map(res => res.json ()) } }
  • 如果没有 cuser.token,你也应该返回一个 observable
【解决方案2】:

您可以将第二个要运行的函数放在第一个函数的订阅方法的成功部分。

getServiceTicket() {
    this.userAuthServie.getServiceTicket().subscribe(
        (data: string) => {
            this.serviceTicket = data; this.isServiceTicket = true;
            this.getDetail(id);
        }
    );
}

【讨论】:

  • 非常感谢您的回答。我还有一个问题,我实现这种方式的原因是我想实现单独获取服务票证的方法,这意味着每当我需要服务票证时,我想在实际 http 请求之前调用该方法并获取服务票并将该服务票传递给真正的http请求方法。如果我以这种方式实现,我必须重复以下代码。 "this.userAuthServie.getServiceTicket().subscribe(" 所以...
  • 您可以使用两个单独的方法来执行此操作,也可以简单地在同一方法中创建一个 if 语句来执行或不执行您所指的部分,具体取决于您传递的布尔值。跨度>
【解决方案3】:

如果您想在执行任何“详细请求”之前等待加载服务票证,则应等待服务票证的响应以解决。有多种方法,一种方法可能是将详细信息添加到队列中,或者让 getDetails 等待服务票证加载完毕。

getServiceTicket() {
    // you need to return the observable from service ticket
    return this.userAuthServie
       .getServiceTicket()
       // use map here to only intercept the value.
       // remember that you need to subscribe somewhere else
       // if called from elsewhere than getDetail
       .map((data: string) => {
           this.serviceTicket = data;
           this.isServiceTicket = true;
           return data;
       });
}

getDetail(id: string) {
    return this.getServiceTicket()
        // we switch the observable from ticket to the one from detail using switchMap
        .switchMap((data: string) => {
            let url = 'https://localhost/detail/' + id + '?ticket=' + this.serviceTicket;
            return this.http
                .get(url)
                .map((responseData) => {
                    return <User>responseData.json();
                });
        });
    }
}

【讨论】:

  • 非常感谢,但我得到这个“属性 'switchMap' 不存在于类型 'Observable' 上。如果你有一些线索,你能解释一下吗?
  • switchMap 有什么问题?