Angular: 每次需要更新的时候我应该订阅()到http.get()吗?
Angular: Should I subscribe() to http.get() each time I need to update?
我想知道我是否使用了 Observable.subscribe() 太多次。
在我的组件 class 中,我有一个函数 loadData()。
它调用另一个函数 this.service.getData(),该函数使用 HttpClient.get() 向服务器执行 HTTP 请求。
目前在我的函数 loadData() 中,我订阅了 this.service.getData() 的结果。
每次用户点击 "Update" 按钮时,我想调用我的函数 loadData()。
问题
- 如果我每次需要执行 HTTP 请求时都调用我的函数 loadData(),我会创建同样多的订阅者吗?
- 是否存在内存泄漏的风险?
- 如果是这样,你知道我应该如何重构我的代码吗?
答案
- 我找到了另一个 post
- 说明Angular代码实际上是在HTTP请求后调用observable.complete(),有延迟
- 所以我修改了下面的代码来检查这个事实,测试证实这是真的
代码示例
private loadData() {
this.loading = true;
const subscription = this.service.getData()
.pipe(
// console.log() with a delay added for test - START
map(val => {
window.setTimeout(() => {
// This will print true.
console.log('After delay: Is Subscriber closed?', subscription.closed);
}, 10);
return val;
}),
// console.log() with a delay added for test - END
takeUntil(this.ngUnsubscribe))
.subscribe(data => {
this.data = data;
// This will print false.
console.log('Is Subscriber closed?', subscription.closed);
},
error => {
console.error(error);
throw error;
},
() => {
this.loading = false;
});
}
getData(): Observable<DataObject> {
const uri = encodeURI(this.configService.getUri());
const headers = new HttpHeaders();
if (this.pipelineEtag) {
headers.set('If-None-Match', this.pipelineEtag);
}
return this.http.get(uri, {
headers: headers,
observe: 'response'
}).pipe(
map(resp => this.processResponse(resp)),
catchError(error => this.handleError(error, this.envProduction))
);
}
这是正确的用法,创建多个订阅者没有风险。
来自文档:
The AsyncPipe subscribes (and unsubscribes) for you automatically.
技术细节是,一旦 Http 请求完成,就会调用可观察对象的 .complete
方法,这会杀死所有当前订阅者。这意味着您的订阅者已创建、使用并立即被丢弃。
每次 HTTP 调用 returns 一个值时,Observable 就会完成。所以在服务中做这样的事情是安全的
loadData() {
return this.http.get<Data>(dataUrl).pipe(
// tap(data => console.log(data)), // eyeball results in the console
catchError(err => this.handleError(err))
);
}
然后调用
this.service.loadData().subscribe((data:Data) => do somthing)
您甚至可以调用 exhaustMap 或 switchMap 来控制 Observable 流程,以免 "hint" 服务器占用太多时间
所以最后
- 我找到另一个 post :
- 说明Angular代码实际上是在HTTP请求后调用observable.complete(),有延迟
- 所以我修改了下面的代码以检查该事实和测试
证实是真的
我想知道我是否使用了 Observable.subscribe() 太多次。
在我的组件 class 中,我有一个函数 loadData()。 它调用另一个函数 this.service.getData(),该函数使用 HttpClient.get() 向服务器执行 HTTP 请求。
目前在我的函数 loadData() 中,我订阅了 this.service.getData() 的结果。
每次用户点击 "Update" 按钮时,我想调用我的函数 loadData()。
问题
- 如果我每次需要执行 HTTP 请求时都调用我的函数 loadData(),我会创建同样多的订阅者吗?
- 是否存在内存泄漏的风险?
- 如果是这样,你知道我应该如何重构我的代码吗?
答案
- 我找到了另一个 post
- 说明Angular代码实际上是在HTTP请求后调用observable.complete(),有延迟
- 所以我修改了下面的代码来检查这个事实,测试证实这是真的
代码示例
private loadData() {
this.loading = true;
const subscription = this.service.getData()
.pipe(
// console.log() with a delay added for test - START
map(val => {
window.setTimeout(() => {
// This will print true.
console.log('After delay: Is Subscriber closed?', subscription.closed);
}, 10);
return val;
}),
// console.log() with a delay added for test - END
takeUntil(this.ngUnsubscribe))
.subscribe(data => {
this.data = data;
// This will print false.
console.log('Is Subscriber closed?', subscription.closed);
},
error => {
console.error(error);
throw error;
},
() => {
this.loading = false;
});
}
getData(): Observable<DataObject> {
const uri = encodeURI(this.configService.getUri());
const headers = new HttpHeaders();
if (this.pipelineEtag) {
headers.set('If-None-Match', this.pipelineEtag);
}
return this.http.get(uri, {
headers: headers,
observe: 'response'
}).pipe(
map(resp => this.processResponse(resp)),
catchError(error => this.handleError(error, this.envProduction))
);
}
这是正确的用法,创建多个订阅者没有风险。
来自文档:
The AsyncPipe subscribes (and unsubscribes) for you automatically.
技术细节是,一旦 Http 请求完成,就会调用可观察对象的 .complete
方法,这会杀死所有当前订阅者。这意味着您的订阅者已创建、使用并立即被丢弃。
每次 HTTP 调用 returns 一个值时,Observable 就会完成。所以在服务中做这样的事情是安全的
loadData() {
return this.http.get<Data>(dataUrl).pipe(
// tap(data => console.log(data)), // eyeball results in the console
catchError(err => this.handleError(err))
);
}
然后调用
this.service.loadData().subscribe((data:Data) => do somthing)
您甚至可以调用 exhaustMap 或 switchMap 来控制 Observable 流程,以免 "hint" 服务器占用太多时间
所以最后
- 我找到另一个 post :
- 说明Angular代码实际上是在HTTP请求后调用observable.complete(),有延迟
- 所以我修改了下面的代码以检查该事实和测试 证实是真的