在组件销毁后,当挂起的api调用完成时,订阅不会更新为最新值



parent component.html

<child-component *ngIf="showChild"></child-component>

儿童component.ts

@UntilDestroy()
@Component({
selector: 'child-component',
templateUrl: './child-component.html',
styleUrls: ['./child-component.scss']
})
export class MyChildComponent implements OnInit, OnDestroy {
myStoreData
constructor(store) {
this.store
.select(myData)
.pipe(untilDestroyed(this))
.subscribe((myStoreData) => (this.myStoreData= myStoreData));
}
async makeApiCall() {
try {
let x = await fetch(api) // <-- Lets say this took 5 seconds, and the component was destroyed when this was ongoing
this.store.dispatch(myActionThatChangesMyStoreData({ data: x ))
if (this.myStoreData.someCondition) {  // <-- after api is finished and this executed (and the component is destroyed), myStoreData still has old stale data and is not changed from the "myActionThatChangesMyStoreData" action.
this.store.dispatch(myOtherAction({ data: "abc" ))
}
}
catch (error) {
}
}
}

当组件被销毁时,我通常取消订阅所有订阅。为此,我使用了until-destroy库。

当makeApiCall在子组件中执行并且parent中的showChild变量被设为false时,子组件将被销毁,因此所有来自store的订阅都会因为untilDestroy而被销毁。但是组件仍然在内存中,因为有一个挂起的xhr请求,并且当请求完成时,进一步的操作将处理过时的存储数据(因为所有订阅都被取消订阅),并且整个函数逻辑出错。

简而言之,当组件被销毁时,如何确保在挂起的xhr请求完成后获得最新的存储数据?我可以想到一些hack,比如在xhr请求完成后,检查组件是否被销毁(通过isDestroyed变量),如果该变量为真,则再次订阅以从存储中获取最新值,然后立即取消订阅。但是有没有更好的方法来处理这些情况

谢谢!

将整个ASYNC功能移动到效果。创建一个新的动作,它将从组件中调度,API调用的整个逻辑将在效果中发生。

这样,即使组件被销毁了,所有的东西也会按原样更新。

//change
async makeApiCall() {
...
}
// to
fetchData() {
this.store.dispatch(myFetchDatAction());
}
//and have the effect ready
//data.effects.ts
fetchData$ = createEffect(() =>
ofType(myFetchDatAction),
switchMap(() => {
// do the async stuff here
})
)

最新更新