Angular 进行订阅以等待响应

问题描述 投票:0回答:6

我正在尝试订阅 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);
javascript angular typescript asynchronous
6个回答
6
投票

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

     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


4
投票

这是正常行为,因为您的

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() 将其用作 Promise 并将方法更改为异步:

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

 }

2
投票

是的,因为Javascript是逐行解释执行的,因此它不会等待其他进程完成。这就是为什么最后一个控制台将返回未定义的原因。同时,如果您使用订阅者内部的控制台,那么您将获得正确的日志,因为订阅者将等待响应并将其与 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 getAsyncData() {
    this.asyncResult = await this.httpClient.get<Employee>(this.url).toPromise();
    console.log('No issues, I will wait until promise is resolved..');
  }

1
投票

你可以这样做..

你的组件文件如下

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>

此实时链接中的演示Stackblitz 链接


0
投票

我会采用不同的方式:如果您必须重新映射值,您可以使用

map
运算符:


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

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


0
投票

如何订阅《克服它》

© www.soinside.com 2019 - 2024. All rights reserved.