angular - 如何从我的服务提供商的共享 HTTP 请求中捕获 401?

标签 angular http typescript ionic-framework ionic2

我正在使用 Ionic 2 创建移动应用程序。 Ionic 2 使用 Angular 2。

我的逻辑很简单。我有一个 api 服务,它有 get()post() 方法,用于发送/检索带有 auth header 和 get_no_auth( )post_no_auth() 用于没有授权 header 的请求。

这些方法是从其他服务为应用程序的特定部分(usertraining_programme 等)调用的。

一切正常,但我需要从 API 捕获 401 HTTP 状态代码并采取适当的措施。

我的 api.js 服务:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, URLSearchParams } from '@angular/http';
import { Storage } from '@ionic/storage';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/catch';

@Injectable()
export class Api {
  base_url: string = 'https://*****.com';
  url: string = this.base_url + '/api/v1';
  authurl: string = this.base_url + '/oauth/token';
  grant_type: string = 'password';
  client_id: string = '1';
  client_secret: string = '*****';
  access_token: string;

  constructor(
    public http: Http, 
    private storage: Storage) {

    // Grab access token and store it
    storage.get('access_token').then((val) => {
      this.access_token = val;
    });
  }

  // Performs a GET request with auth headers
  get(endpoint: string, params?: any) {
    if(!params) {
      params = [];
    }
    params['grant_type'] = this.grant_type;
    params['client_id'] = this.client_id;
    params['client_secret'] = this.client_secret;

    let headers: Headers = this.getHeaders();

    return this.getApiToken().flatMap(data => {

      headers.append('Authorization', 'Bearer ' + data);

      let options = new RequestOptions({ headers: headers });

      // Support easy query params for GET requests
      if (params) {
        let p = new URLSearchParams();
        for (let k in params) {
          p.set(k, params[k]);
        }
        // Set the search field if we have params and don't already have
        // a search field set in options.
        options.search = !options.search && p || options.search;
      } 

      return this.http.get(this.url + '/' + endpoint, options);
    }).share();
  }
}

我通过特定于每个实体的提供商来调用它。因此对于培训计划:

  get_programmes() {
    let seq = this.api.get('training-programmes');

    seq
      .subscribe();

    return seq;
  }

我从我的 Controller 中调用它:

this.trainingProgramme.get_programmes()
    .map(res => res.json())
    .subscribe((res) => {

    loader.dismiss();
    this.currentItems = res.training_programmes;

}, (err) => {
    loader.dismiss();
});

我宁愿不在我的 Controller 中处理 401,因为它会导致我的应用程序中出现重复代码。相反,我想在 api.js 服务文件中捕获任何 401 状态代码。

我该怎么做?我尝试向 http.get 添加 catch 语句,但这会导致错误。

Argument of type '(e: any) => void' is not assignable to parameter of type '(err: any, caught: Observable<Response>) => ObservableInput<{}>'. Type 'void' is not assignable to type 'ObservableInput<{}>'.

最佳答案

处理错误的最简单方法是像您尝试的那样使用 catch 语句。要使其正常工作,您必须从错误处理程序返回一个可观察对象(错误消息告诉您缺少返回语句)。

private handleError(error: any) {
    let errMsg: string;
    if (error.status === 401) {
        errMsg = 'Got error 401';
    }
    else {
        errMsg = 'Got some other error';
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
} 

关于angular - 如何从我的服务提供商的共享 HTTP 请求中捕获 401?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45439071/

相关文章:

angular - 在 Angular 6 中设置文件输入的值

node.js - 使用 Docker 容器的 MEAN 堆栈

html - 我想在点击登录按钮后导航到另一个页面

http - 如何检查使用 `http-client` 创建的传出 HTTP 请求的主体 (Haskell)

http - 静态文件加载失败:net::err_content_length_mismatch

angular - 类型错误 : Object prototype may only be an Object or null: undefined Angular 8

javascript - Typescript 的代码覆盖率

angular - 如何在 Angular 应用程序中提供 favicon.png 而不是 favicon.ico?

angularjs - 在 1.2+ 中从 $http 返回数据时,模板缓存中的模板不呈现绑定(bind)

typescript - 如何在 try-catch block 中输入 Firebase JS SDK 错误?