【问题标题】:Wait for multiple HTTP calls to end before doing something在做某事之前等待多个 HTTP 调用结束
【发布时间】:2018-08-09 16:44:12
【问题描述】:

我想进行两次 HTTP 调用。

下面是我的 TypeScript 代码

   CheckLogIn() {
    this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode).subscribe(result => {
      setTimeout(() => {
        if (result == true) {
          this.GetUserName();
          sessionStorage.setItem("UserID", this.StaffCode);
          this.router.navigate(['/log-tracker']);
        }
      }, 5000)
    }, error => console.log(error));
  }

 GetUserName() {
    this.http.get(this.baseUrl + 'api/Common/GetUserName/' + sessionStorage.getItem("UserID"), { responseType: 'text' }).subscribe(result => {
      console.log(result);
      sessionStorage.setItem("UserName", result);
    }, error => console.log(error));
  }

在 CheckLogin() 内部,我正在调用一个端点,在此调用的响应中,我正在调用另一个端点 (GetUserName),然后重定向到另一个页面。

但 checkLogin 不会等待 GetUserName 完成并在第二次调用完成之前重定向到页面,因此会话用户名始终为空。

我尝试使用 SetTimeout 函数,但它在这里不起作用,有没有其他方法可以在重定向之前设置延迟,或者有任何方法让第一次调用等到第二次调用完成它的工作?

【问题讨论】:

  • 我编辑您的问题,因为您没有使用两个 API。
  • this.router.navigate(['/log-tracker']); 这必须在 GetUserName 订阅方法中。
  • 使用switchMap
  • @trichetriche,谢谢,但再看一遍,希望你能找到两个 api 的
  • @SujataChanda ,我会尝试这个想法

标签: angular


【解决方案1】:

您没有在CheckLogin 中等待GetUserName,您只是在调用它并忽略结果。您可以尝试从 GetUserName 返回 observable - 这里还有一个使用其他 RXJS 运算符的好机会。

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/do';

CheckLogIn() {
  this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode)
    .filter(result => result)
    .do(() => sessionStorage.setItem("UserID", this.StaffCode))
    .mergeMap(() => this.GetUserName())
    .subscribe( // This does not execute until the observable from GetUserName is complete
       result => this.router.navigate(['/log-tracker']),
       error => console.log(error)
    );
}

GetUserName() { // I now return an observable
  return this.http.get(this.baseUrl + 'api/Common/GetUserName/' + sessionStorage.getItem("UserID"), { responseType: 'text' })
    .do(result => sessionStorage.setItem("UserName", result));
}

现在我们执行以下操作:

  1. 致电CheckLogin
  2. 如果结果为真,继续
  3. 在会话存储中设置UserID
  4. 致电GetUserNamereplace our observable with it
  5. GetUserName 返回的 observable 完成后,我们可以导航

没有必要用 Promise 替换 RXJS,它在你执行异步请求时有很大的威力——尤其是在这样的情况下,当你有多个调用以特定的顺序执行时,并且条件有会遇到的。

【讨论】:

  • .mergeMap(this.GetUserName()) 如果没有绑定,这将无法工作。
  • 什么意思?不打电话给.bind?肯定会的,此时我们仍在课程的上下文中,所以this 应该是我们所期望的。
  • 等一下,对不起,你确实做了调用——我把它读为函数传递——我的错。
  • 既然你提到了它,我相信它应该是一个函数,而不仅仅是对GetUserName的调用,但是使用箭头函数应该可以防止丢失this上下文,
  • @Jack 我在stackblitz.com/edit/angular-utzj3i 创建了一个非常粗略的示例,您可以看到确实发生了 API 调用并且发生了导航。您确定要调用 CheckLogIn 方法吗? @Antoniossss 据我所知pipe 的存在是为了更容易地重用代码,这在这里不是很相关。我理解一个导入少于三个的论点,但我认为您最终仍会导入 filter,这使得它几乎不值得付出努力,并且在我看来会降低可读性。
【解决方案2】:

你可以使用 Promise

CheckLogIn() {
  try {
    return new Promise((resolve, reject) => {
      this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode).subscribe(result => {
        setTimeout(() => {
          if (result == true) {
            this.GetUserName();
            sessionStorage.setItem("UserID", this.StaffCode);
            this.router.navigate(['/log-tracker']);
          }
        }, 5000)
      }, error => console.log(error));
      resolve();
    })
  } catch (error) {
    console.log(error);
  }
}

像这样调用你的 Checklogin 函数

this.CheckLogIn().then(()=>{
      this. GetUserName();
    });

【讨论】:

  • 没有必要在 promise 中包装 observable。 Observables 具有 Promise 的所有功能等等。
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2014-11-27
  • 1970-01-01
相关资源
最近更新 更多