Действие отправки перед вызовом http в @ ngrx / Effects - PullRequest
0 голосов
/ 30 августа 2018

Я хочу сделать http-вызов для этого я использую эффект от rxjs. Теперь моя проблема в том, что я хочу отправить еще одно действие, например { type: LoaderActions.LOADER_START }, перед вызовом http. Таким образом, пользователь может видеть экран загрузки, пока запрашивается Http-вызов, и после завершения запроса я хочу отправить еще одно действие { type: LoaderActions.LOADER_END }.

Как мне добиться этого с помощью операторов rxjs? Я очень озадачен тем, когда использовать какой оператор в rxjs.

auth.effects.ts

import { Injectable } from '@angular/core';
import { Observable, of, concat } from 'rxjs';
import { Action, Store } from '@ngrx/store';
import { Actions, Effect, ofType } from '@ngrx/effects';
import * as AuthActions from './auth.actions';
import * as LoaderActions from '../../loader/store/loader.actions';
import {
  map,
  mergeMap,
  switchMap,
  debounce,
  debounceTime,
  tap,
  startWith
} from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json; charset=utf-8'
  })
};
@Injectable()
export class AuthEffects {
  @Effect()
  signInAction$: Observable<Action> = this.actions$.pipe(
    ofType(AuthActions.TRY_SIGN_IN),
    mergeMap(action =>
      this.http
        .post(
          'http://localhost:8081/auth',
          JSON.stringify({
            username: action['username'],
            password: action['password']
          }),
          httpOptions
        )
        .pipe(
          map(data => {
            if (data['message'] === 'successs') {
              this.router.navigate(['/todo']);
              return { type: AuthActions.SET_AUTH_FLAG, payload: true };
            } else {
              return { type: AuthActions.SET_AUTH_FLAG, payload: false };
            }
          })
        )
    )
  );

  constructor(
    private actions$: Actions,
    private http: HttpClient,
    private router: Router
  ) {}
}

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

Вы можете использовать concat, где первым наблюдаемым источником будет действие загрузки.

@Effect()
signInAction$: Observable<Action> = this.actions$.pipe(
  ofType(AuthActions.TRY_SIGN_IN),
  concatMap(action => concat(
    of({ type: LoaderActions.LOADER_START }),
    this.http...
    of({ type: LoaderActions.LOADER_END }),
  ))
)

Оператор concat позаботится о том, чтобы действия были созданы по порядку.

0 голосов
/ 30 августа 2018

Вы не должны использовать дополнительные действия для своих целей. Просто добавьте свойство loading: boolean в ваш штат и установите его false по умолчанию. Когда вы отправляете TRY_SIGN_IN, вы можете установить его на true в редукторе. Когда http приходит либо с успехом, либо с ошибкой, вы можете снова установить состояние загрузки в false с отправкой действия SET_AUTH_FLAG.

Затем вы можете выбрать состояние загрузки с помощью правильного селектора, но я думаю, вы знаете, что я имею в виду, и использовать его с трубкой Angulars async в своих шаблонах.

0 голосов
/ 30 августа 2018

Вы должны создать на слушателе эффекта больше для ofType(AuthActions.TRY_SIGN_IN) и сопоставить это действие с излучением { type: LoaderActions.LOADER_START }. Тогда, по вашему мнению, вы должны

switchMap(data => {
            if (data['message'] === 'successs') {
              this.router.navigate(['/todo']);
              return [{ type: AuthActions.SET_AUTH_FLAG, payload: true }, { type: LoaderActions.LOADER_END }];
            } else {
              return [{ type: AuthActions.SET_AUTH_FLAG, payload: false }, { type: LoaderActions.LOADER_END }];
            }
          })

При таком подходе вы получите желаемое поведение: Действие загрузчика и http-запрос выполняются одновременно, и, когда http-запрос будет завершен, он отправит действия для установки флага авторизации и удаления загрузчика

...