Angular - 组件存储,为什么我的效果在http错误后无法触发?

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

第一次在 Angular 项目中使用组件存储作为简单的状态管理。

我可能不完全理解

effect()
componentStore
是如何工作的。

当用户想要删除某个项目时,我打开一个对话框,确认后我调用我的存储方法:

public delete(entity: any): void {
    const dialogRef = this._dialog.open(
        // ....
    );

    dialogRef.afterClosed().subscribe(result => {
        if (result && result === true) {
            this.myStore.delete(entity.id);
        }
    });
}

这是

myStore
删除效果:

public readonly delete = this.effect((id$: Observable<string>) => {
    return id$.pipe(
        switchMap(id => this.myApiService.delete(id)),
        catchError(err => of(err as string)),
        tap(id => {
            this.removeLocalItem(id);
        }),
    );
});

我的api服务中的最后一个方法:

public delete(id: string): Promise<string> {
    const response = firstValueFrom(
        this._httpClient.delete<void>(`my endpoint`).pipe(
            map(() => id),
            catchError(error => {
                console.log(error);
                return '';
            }),
        ),
    );

    return response;
}

所以基本上如果我从列表中删除(成功的 api 调用)多个项目, 一切都很顺利。

但是一旦一项

delete
调用由于后端错误响应而失败, 它正确记录了错误,但现在在应用程序中,无论我尝试删除什么,都没有发生任何事情,似乎不再调用该效果。

如果我在调用存储组件效果的对话框中放置一个

console.log
,日志会正确打印,只是看起来什么也没发生,并且
delete()
没有被调用。

我可以假设这与这些

effect()
是可观察的,所以有些东西我不明白。

为什么删除成功后还继续工作,但一旦删除失败,其他try就不会调用该方法了?

我尝试查看文档,但组件商店并没有回答我的疑问

编辑:经过一些测试,我发现如果我的

api method
,在
ApiService
中,而不是使用
firstValueFrom
/
lastValueFrom
并使该方法成为
promise
,如果我只是将其变成
observable
,并返回
http call
,那么即使发生错误,一切也能正常工作。

我想了解我应该更改什么才能使其与承诺一起工作,我假设我在某处使用了错误的运算符

angular ngrx ngrx-component-store
1个回答
1
投票

发生错误时,

firstValueFrom
可能会导致可观察流完成或取消订阅,这可能会阻止未来的排放达到效果。

  • 带有可观察的 您可以直接从 API 服务返回可观察量,而不是将可观察量转换为承诺。

    public delete(id: string): Observable<string> {
       return this._httpClient.delete<void>(`my endpoint`).pipe(
         map(() => id),
         catchError(error => {
           console.log(error);
           return of('');
         }),
       );
    }
    

    在组件存储中,您可以使用

    pipe
    运算符来处理来自 API 服务的响应:

    public readonly delete = this.effect((id$: Observable<string>) => {
       return id$.pipe(
         switchMap(id => this.myApiService.delete(id).pipe(
           catchError(err => of(err as string)),
         )),
         tap(id => {
           if (typeof id === 'string') {
             this.removeLocalItem(id);
           }
         }),
       );
    });
    
  • 有承诺 为了让它与 Promise 一起工作,你可以尝试拒绝 Promise

public delete(id: string): Promise<string> {
    return firstValueFrom(
        this._httpClient.delete<void>(`my endpoint`).pipe(
            map(() => id),
            catchError(error => {
                console.log(error);
                return Promise.reject(''); // Reject the promise
            }),
        ),
    );
}

这样,如果发生错误,它将拒绝 Promise,并且流中的任何后续操作都会意识到该错误。

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