Angular 订阅以等待响应

Angular make subscribe to wait for response

我正在尝试订阅 Observable 并从响应中分配一些数据,但不知何故我的代码没有等待响应。基本上 console.log(this.newIds) 首先运行并且始终为空,因为订阅不等待来自后端的响应。我如何强制我的代码等待响应的到来?

 this.repository.getById(Ids).subscribe((response) => {
      console.log(response);
      this.newIds = response.map((id) => {
        return id;
      });
    });
    console.log(this.newIds);

如果您将代码放在订阅回调中。它将在您收到 back-end 的响应后执行。您在该函数之外编写的所有代码都将直接执行。

     this.repository.getById(Ids).subscribe((response) => {
          //Code will execute when back-end will respond
          console.log(response);
          this.newIds = response.map((id) => {
            return id;
          });
          console.log(this.newIds);
        });
//Code will execute immediately

另请参阅:https://angular.io/guide/observables#creating-observables

这是正常行为,因为您的 console.log(this.newIds); 在订阅之外,您只需要将它移到 .subscribe() 方法中:

 this.repository.getById(Ids).subscribe((response) => {
          console.log(response);
          this.newIds = response.map((id) => {
            return id;
          });
          console.log(this.newIds);
    });

如果你想在订阅之外使用 this.newIds 并在观察者的结果之后立即使用,你可以使用 RxJs .toPromise() 将其用作承诺并将方法更改为异步:

async callerFn(){

    const response = await this.repository.getById(Ids).toPromise();
  
    this.newIds = response.map((id) => {
        return id;
    });
    console.log(this.newIds);
    // use your property here

 }

是的,因为 Javascript 正在解释 line-by-line 执行,因此它不会等待其他进程完成。这就是为什么最后一个控制台将 return 未定义的原因。同时,如果您使用订阅者内部的控制台,那么您将获得正确的日志,因为订阅者将等待响应并将其与 this.newIds

绑定
 this.repository.getById(Ids).subscribe((response) => {
      console.log(response);
      this.newIds = response.map((id) => {
        return id;
      });
     console.log(this.newIds);
    });

在这里,我附上了一篇关于可观察订阅的好读物

https://betterprogramming.pub/observables-vs-promises-which-one-should-you-use-c19aef53c680

除此之外,如果您想在订户范围之外使用 newIds 访问权限,请将 promise 与 async await 结合使用。这里我添加了一个示例

 async getAsyncData() {
    this.asyncResult = await this.httpClient.get<Employee>(this.url).toPromise();
    console.log('No issues, I will wait until promise is resolved..');
  }

我会以不同的方式处理:如果您必须重新映射值,您可以使用 map 运算符:


 this.repository.getById(Ids)
  .pipe(map(response) => response.map(id => id))
  .subscribe((id) => {
      console.log(response);
      this.newIds = id;
  });

实际上,我不明白为什么你需要映射一个你已经拥有的值,但我认为这是明确的解决方案。

你可以这样做..

您的组件文件如下所示

newIds: Observable<any> = of(this.id).pipe(
concatMap((id) =>
  this.getId(id).pipe(map((data) => data.map((rowId) => rowId.id)))
)
);
getId(id: any) {
  return of([{ id: 1 }, { id: 2 }, { id: 3 }]);
}

您的 html 文件如下所示,并使用异步管道进行订阅。在这里你可以使用 concateMap 管道 rxjs 运算符顺序调用 observable,然后将值赋给你的 newId 变量。

<pre>
  {{ newIds | async }}
</pre>

现场演示linkStackblitz Link