NGRX/Effects 将数据传递给 catchError

NGRX/Effects pass data through to catchError

要点

我有一个效果,通过多个 API 请求加载产品评论:

@Effect()
    loadOfProduct$ = this.actions$.pipe(
        ofType<ReviewsActions.LoadOfProduct>(ReviewsActions.Types.LOAD_OF_PRODUCT),
        map(action => action.payload),
        switchMap((productId: string) => {
            return this.reviewsService.loadOfProduct(productId);
        }),
        switchMap((reviews: Review[]) => {
            return forkJoin([
                of(reviews),
                this.productsService.loadManyById(reviews.map(r => r.productId)),
                this.usersService.loadManyById(reviews.map(r => r.writerId)),
            ]);
        }),
        switchMap((data: any) => {
            const [reviews, products, users] = data;
            return [
                new ProductsActions.LoadManyByIdSuccess(products),
                new UsersActions.LoadManyByIdSuccess(users),
                new ReviewsActions.LoadOfProductSuccess(reviews),
            ];
        }),
        catchError(error => of(new ReviewsActions.LoadOfProductFail({
            ...error.error,
            // I need the productId here!!!
            // payload: productId,
        }))),
    );

问题

问题是,我不知道如何从 catchError

中的第一个 switchMap 访问 productId 字符串

只需将下一个运算符嵌套在第一个 switchMap 下:

    @Effect() loadOfProduct$ = this.actions$
    .pipe(
        ofType<ReviewsActions.LoadOfProduct>(ReviewsActions.Types.LOAD_OF_PRODUCT),
        switchMap((action) => {
            const productId = action.payload;
            return this.reviewsService.loadOfProduct(productId)
                .pipe(
                    switchMap((reviews: Review[]) => {
                        return forkJoin([
                            of(reviews),
                            this.productsService.loadManyById(reviews.map(r => r.productId)),
                            this.usersService.loadManyById(reviews.map(r => r.writerId)),
                        ]);
                    }),
                    switchMap((data: any) => {
                        const [reviews, products, users] = data;
                        return [
                            new ProductsActions.LoadManyByIdSuccess(products),
                            new UsersActions.LoadManyByIdSuccess(users),
                            new ReviewsActions.LoadOfProductSuccess(reviews),
                        ];
                    }),
                    catchError(error => of(new ReviewsActions.LoadOfProductFail({
                        ...error.error,
                        // now you have the productId
                        // payload: productId,
                    })))
                );
        })
    );

或者如果 reviewsService.loadOfProduct 方法 returns 一个承诺:

return from(this.reviewsService.loadOfProduct(productId)) // originally fromPromise
    .pipe(...)

这也是处理 effects 内部错误的正确方法,因为在原始代码中,如果发生错误,"effect" 将停止工作,即使它进入了 catchError 运算符。

有关此内容的更多信息,请查看