我正在尝试订阅 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);
如果将代码放在订阅回调中。它将在您收到后端的响应后执行。您在该函数之外编写的所有代码都会直接执行。
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() 将其用作 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
}
是的,因为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..');
}
你可以这样做..
你的组件文件如下
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 链接
map
运算符:
this.repository.getById(Ids)
.pipe(map(response) => response.map(id => id))
.subscribe((id) => {
console.log(response);
this.newIds = id;
});
实际上,我不明白为什么您需要映射已有的值,但我认为这是明确的解决方案。
如何订阅《克服它》