在HttpClient中使用ngrx效果时,“未定义响应”

时间:2018-07-10 16:11:34

标签: angular5 ngrx

我目前正在重写旧的请求服务,以使用HttpClient而不是Http。我的应用程序使用了ngrx存储,在我重写请求服务后,它停止工作。 这是我的请求服务:

import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import { ToastController } from 'ionic-angular';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Config } from '../app/app.config';
import {Observable} from 'rxjs/Rx';


import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Version } from '@angular/compiler';

export enum HttpStatus {
  UNAUTHORIZED,
  WRONGVERSION,
  UNVERIFIED,
  NONETWORK,
}

export interface HttpNotifierData {
  status: HttpStatus
}

@Injectable()
export class HttpClientService {
  private httpNotifier: ReplaySubject<HttpNotifierData>;

  constructor(
    public toastCtrl: ToastController,
    private _http: HttpClient,
  ) {
    this.httpNotifier = new ReplaySubject();
  }

  createHeaders(contentType?: string) {
    var headers = new HttpHeaders();
    let token = localStorage.getItem('auth_token');
    let expires = localStorage.getItem('auth_expires');
    let appVersion = Config.version+'';


    if(token)
      headers = headers.set( 'Authorization', 'Bearer ' + token);
    if(expires)
      headers = headers.set( 'TokenExpiration', expires);
    if(appVersion)
      headers = headers.set( 'App-Version', appVersion);  

    if(contentType === 'form')
        headers = headers.set('Content-Type','application/x-www-form-urlencoded');
    return headers;
  }

  createAppVersionHeader(headers: Headers) {
    let appVersion = Config.version+'';
    headers.append('App-Version', appVersion);
  }

  getHttpNotifier(): ReplaySubject<HttpNotifierData> {
    return this.httpNotifier;
  }

  request(verb: string, url: string, data?: any, contentType?: string) {

    let headers = this.createHeaders(contentType);
    return this._http.request(verb, url, {
      body: data,
      headers: headers
    }).catch(err => {
      if (err.status == 0) {
        this.httpNotifier.next({status: HttpStatus.NONETWORK});
        err._body = 'Kunne ikke kontakte baksystem';
      } else if (err.status == 401) {
        this.httpNotifier.next({status: HttpStatus.UNAUTHORIZED});
      } else if (err.status == 403) {
        this.httpNotifier.next({status: HttpStatus.UNVERIFIED});
      } else if (err.status == 412) {
        this.httpNotifier.next({status: HttpStatus.WRONGVERSION});
      } else {
        // TODO: Convert API error to user friendly error
        this.toastCtrl.create({
          message: err._body,
          duration: 3000,
          showCloseButton: true,
          closeButtonText: "Lukk",
          cssClass: 'error',
        }).present();
      }
      throw err;
    });
  }

  get(url) {
    let cache = '?cache=' + Math.ceil(Math.random() * 100000);
    return this.request('GET', url + cache);
  }

  post(url, data, contentType = 'json') {
    return this.request('POST', url, data, contentType);
  }

  put(url, data) {
    return this.request('PUT', url, data);
  }

  delete(url) {
    return this.request('DELETE', url);
  }

}

我的用户身份验证服务:

import { Injectable } from '@angular/core';
import { Config } from '../app/app.config';
import { HttpClientService } from "./http.service";

@Injectable()
export class UserService {
  constructor(
    private _http: HttpClientService
  ) { }

  login(username: string, password: string) {
    var data = "grant_type=password&username=" + username + "&password=" + password + "&deviceId=test";
    return this._http.post(Config.apiUrl + 'Token', data, 'form');
  }

  getPin(phone: string) {
    return this._http.post(Config.apiUrl + 'api/account/forgotPassword', {phoneNumber: phone})
  }
}

我的用于验证用户身份的ngrx效果:

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/observable/of';

import { Injectable } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../services/user.service';
import * as UserActions from '../actions/user.actions';


@Injectable()

export class UserEffects {

  constructor(
    private actions: Actions,
    private userService: UserService
  ) {}

  @Effect()
  login:Observable<any> = this.actions
    .ofType(UserActions.LOGIN)
    .map((action: UserActions.Login) => action.payload)
    .switchMap(payload => {
      return this.userService.login(payload.username, payload.password)
        .map((response:any) => new UserActions.LoginSuccess(JSON.parse(response._body)))
        .catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
    });

  @Effect()
  getPin:Observable<any> = this.actions
  .ofType(UserActions.GET_PIN)
  .map((action: UserActions.GetPin) => action.payload)
  .switchMap(payload => {
    return this.userService.getPin(payload)
      .map((response: any) => new UserActions.GetPinSuccess())
      .catch((error) => Observable.of(new UserActions.GetPinFailed(error._body)))
  });
}

调试时,我的错误出现在效果模块中: enter image description here

但是,在网络部分,我可以看到请求已成功完成: enter image description here

我的服务有什么问题?

1 个答案:

答案 0 :(得分:1)

好的,所以我想出了解决方案。 登录效果应具有管道并且没有json解析:

@Effect()
  login:Observable<any> = this.actions
    .ofType(UserActions.LOGIN)
    .map((action: UserActions.Login) => action.payload)
    .switchMap(payload => {
      return this.userService.login(payload.username, payload.password).pipe()
        .map((response:any) => new UserActions.LoginSuccess(response))
        .catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
    });