我正在使用Angular开发一个应用程序,我正在try 构建一个包含多个观察值(发出多个值)和HTTP请求(发出一个值)的流.
我想打开一个InApp浏览器,让用户进行交易(付款)并读取回调,这是浏览器将try 加载的新url.我需要订阅浏览器的多个事件,以便在出现错误时获得通知、加载新的url等..
我想正确地处理这个RxJS组合,如果满足某些条件以保证性能且没有潜在的内存泄漏,我会取消所有的可观察值.
我试着遵循:
- RxJS switchMap does not cancel inner merged observable
- Using SwitchMap() to Handle Canceling Previous Requests
- RxJS: switchMap inside merge doesn't work to make a conditional observable return
All the following observables and request are fake to avoid complexity.
Observables that emit one value:
getOrderId(): Observable<any> {
return this.http.get<any>(
'https://jsonplaceholder.typicode.com/posts/1'
);
}
notifyBackend(url: string): Observable<any> {
return this.http.get<any>(
'https://jsonplaceholder.typicode.com/posts/1'
).pipe(delay(2000));
}
Observables that emit multiple values:
Each one will emit at any time, the 100 property will tell the event type and what had happened.
getMultipleOne(): Observable<any> {
return of({type: 'exit'}).interval(3000);
}
getMultipleTwo(): Observable<any> {
return of({type: 'loaderror', url: 'http://www.blabla.com'}).interval(2000);
}
getMultipleThree(): Observable<any> {
// The url returned can be any, I'm waiting for mine.
return of({type: 'loadstart', url: 'http://www.google.com'}).interval(1000);
}
我试图实现的流程是:
- 调用发出一个值并切换到另一个可观察值的
getOrderId
- 同时听三个可观察的多重值.我会对这些事件做出react ,并做一些商业逻辑.
- 如果
type
是exit,取消所有订阅,不通知来电者.表示用户刚刚手动关闭/取消. - 如果
type
是loadstart,判断url,看看切换到另一个HTTP请求是不是我的,或者全部取消. - 如果是我的url,请调用后端保存结果,并通知调用者显示良好的UI结果.
我试过:
initFlow() {
return this.getOrderId() // Emit just one value
.pipe(
// Switch to another one that is the merge of 3 observables
switchMap(() => {
return merge(
getMultipleOne(),
getMultipleTwo(),
getMultipleThree()
);
}),
// This tap will be executed every time the above observables emit something
tap(event => console.log(event)),
tap(event => {
if (event.type === 'exit') {
// Cancel all previous observables if this happen?
// Since the flow is not completed, the caller must not be notified, I guess?
}
}),
filter(event => event.type === 'loadstart'),
pluck('url'),
// If not meet, cancel all above without notifying the caller
switchMap(url => this.isGoogle(url) ? EMPTY : of (url)),
// Switch to another HTTP that emits one value or throw error to cancel all
switchMap(url => {
if (this.isMyPersonalWebSite(url)) {
return this.notifyBackend(url); // Emit just one value
} else {
// Let the caller be notified by its error event to show UI
throw new Error('User transaction is failed');
}
}),
// The previous HTTP just emit one value, this allow the caller to receive the completion event.
// The caller does not need it, but, I guess is the right thing to happen in observables life.
first(),
);
}
来电者:
// This one will be unsubscribed later by the component when its onDestroy hook is called
this.myService.initFlow()
.subscribe({
next: res => console.log('next', res),
error: e => console.log('error', e),
complete: () => console.log('complete')
});
我的问题:
- 在TODO部分,我不知道如何取消之前的所有内容
- 当我返回EMPTY时,我什么也看不到,呼叫者也不在
我的目标是:
- 如果满足条件,则取消所有发出多个值的观测值.
- 当
notifyBackend()
发出时,使用其next事件通知调用者;当我在代码中手动抛出错误时,使用其error事件通知调用者.
如果您有任何关于避免内存泄漏的帮助或建议,以及处理方法,我们将不胜感激.