如何使用@ngrx/effects 进行简单的http 调用?

How to use @ngrx/effects with simple http call?

我有一个非常简单的 http 服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';

import { JsOrder } from '../stores/models/order';

@Injectable({
    providedIn: 'root'
})
export class OrderService {
    private ordersUrl = `${environment.httpApiUrl}/orders`;

    constructor(private http: HttpClient) {}

    fetchOrders(): Observable<JsOrder[]> {
        return this.http.get<JsOrder[]>(this.ordersUrl);
    }
}

我正在尝试从@ngrx/effects 调用它(基于网络上的几个示例):

import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Action } from '@ngrx/store';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { FETCH_ORDERS, LoadOrders } from '../actions';
import { JsOrder, Order } from '../models/order';
import { OrderService } from '../../services/order.service';

@Injectable()
export class OrderEffects {
    constructor(
        private actions$: Actions,
        private orderService: OrderService
    ) {}

    @Effect()
    fetchOrders$: Observable<Action> = this.actions$.pipe(
        ofType(FETCH_ORDERS),
        switchMap(() => {
            return this.orderService
                .fetchOrders()
                .map((jsOrders: JsOrder[]) => {  <---- compilation error here
                    const orders = jsOrders.map(jsOrder =>
                        Order.create(jsOrder)
                    );
                    return new LoadOrders(orders);
                });
        })
    );
}

但是我在上面的 .map() 调用中遇到编译错误:

error TS2339: Property 'map' does not exist on type 'Observable'

正确的做法是什么?

P.S。我也尝试 subscribe() 到 http 服务返回的 Observable(见下文),但这也给出了编译错误(属性 'map' 在类型 'Subscription' 上不存在):

@Effect()
fetchOrders$: Observable<Action> = this.actions$.pipe(
    ofType(FETCH_ORDERS),
    switchMap(() => {
        return this.orderService
            .fetchOrders()
            .subscribe((jsOrders: JsOrder[]) => {
                return jsOrders.map(jsOrder => Order.create(jsOrder));
            })
            .map((orders: Order[]) => new LoadOrders(orders));
    })
);

您必须使用 pipe 和管道运算符:

@Effect()
fetchOrders$: Observable<Action> = this.actions$.pipe(
    ofType(FETCH_ORDERS),
    switchMap(() => {
        return this.orderService
            .fetchOrders()
            .pipe(
                map((jsOrders: JsOrder[]) => {  
                  const orders = jsOrders.map(jsOrder =>
                      Order.create(jsOrder)
                  );
                  return new LoadOrders(orders);
                }),
               catchError(err => of(new LoadOrdersFailure(err)))
            )
    })
);

另外不要忘记捕捉错误。

我遇到了同样的问题。 同时可以通知 effects 停止发送下一个动作。

只需使用 dispatch 标志:

newEffect$ = createEffect(
  () => this.myAction$,
  {dispatch: false}
);