实现 ionic 的本机 HTTP 拦截器时出现打字稿错误
Posted
技术标签:
【中文标题】实现 ionic 的本机 HTTP 拦截器时出现打字稿错误【英文标题】:Typescript error while implementing ionic's native HTTP interceptor 【发布时间】:2020-12-26 13:49:17 【问题描述】:当我遇到一些 CORS 问题时,我正在将已经工作的 Angular 10 网络应用程序修改为离子原生应用程序。由于我无法在 BE 上更改任何内容,因此我遇到了 Ionic 的原生 HTTP 插件。
我按照 Angular 在 how to make an interceptor 和这篇解释 how to implement both HttpClient and Ionic's native HTTP 的文章中的说明进行操作,但遇到了新问题。
使用文章中的代码,TS 抱怨这一行:
headers: nativeHttpResponse.headers
(property) headers?: HttpHeaders
Type ' [key: string]: string; ' is missing the following properties from type 'HttpHeaders': headers, normalizedNames, lazyInit, lazyUpdate, and 12 more.ts(2740)
http.d.ts(3406, 9): The expected type comes from property 'headers' which is declared here on type ' body?: any; headers?: HttpHeaders; status?: number; statusText?: string; url?: string; '
这是整个 native-http.interceptor.ts:
import Injectable from "@angular/core";
import
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
HttpResponse,
from "@angular/common/http";
import Observable, from from "rxjs";
import Platform from "@ionic/angular";
import HTTP from "@ionic-native/http/ngx";
type HttpMethod =
| "get"
| "post"
| "put"
| "patch"
| "head"
| "delete"
| "upload"
| "download";
@Injectable()
export class NativeHttpInterceptor implements HttpInterceptor
constructor(private nativeHttp: HTTP, private platform: Platform)
public intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>>
if (!this.platform.is("cordova"))
return next.handle(request);
return from(this.handleNativeRequest(request));
private async handleNativeRequest(
request: HttpRequest<any>
): Promise<HttpResponse<any>>
const headerKeys = request.headers.keys();
const headers = ;
headerKeys.forEach((key) =>
headers[key] = request.headers.get(key);
);
try
await this.platform.ready();
const method = <HttpMethod>request.method.toLowerCase();
// console.log(‘— Request url’);
// console.log(request.url)
// console.log(‘— Request body’);
// console.log(request.body);
const nativeHttpResponse = await this.nativeHttp.sendRequest(
request.url,
method: method,
data: request.body,
headers: headers,
serializer: "json",
);
let body;
try
body = JSON.parse(nativeHttpResponse.data);
catch (error)
body = response: nativeHttpResponse.data ;
const response = new HttpResponse(
body: body,
status: nativeHttpResponse.status,
headers: nativeHttpResponse.headers, <--------
url: nativeHttpResponse.url,
);
// console.log(‘— Response success’)
// console.log(response);
return Promise.resolve(response);
catch (error)
if (!error.status)
return Promise.reject(error);
const response = new HttpResponse(
body: JSON.parse(error.error),
status: error.status,
headers: error.headers,
url: error.url,
);
return Promise.reject(response);
这是我的app.module.ts
的样子:
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import BrowserAnimationsModule from '@angular/platform-browser/animations';
import IonicModule from '@ionic/angular';
import HTTP from '@ionic-native/http/ngx';
import CoreModule from './core/core.module';
import SharedModule from './shared/shared.module';
import AppComponent from './app.component';
import PageNotFoundComponent from './shared/page-not-found/page-not-found.component';
import appRoutes from './app.routes';
@NgModule(
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
SharedModule,
CoreModule,
RouterModule.forRoot(
appRoutes
),
IonicModule.forRoot()
],
providers: [HTTP],
declarations: [
AppComponent,
PageNotFoundComponent
],
bootstrap: [AppComponent]
)
export class AppModule
这是我的core.module.ts
(我想在其中使用拦截器)的样子:
import NgModule from "@angular/core";
import CommonModule from "@angular/common";
import HTTP_INTERCEPTORS, HttpClientModule from "@angular/common/http";
import NativeHttpInterceptor from "./service/native-http.interceptor";
import AuthService from "./service/auth.service";
import ApiService from "./service/api.service";
import AuthGuardService from "./service/auth-guard.service";
import AuthInterceptor from "./service/auth-interceptor";
import WindowRef from "./service/window-ref-service";
@NgModule(
imports: [CommonModule, HttpClientModule],
providers: [
provide: HTTP_INTERCEPTORS,
useClass: NativeHttpInterceptor,
multi: true,
,
AuthService,
ApiService,
AuthGuardService,
WindowRef,
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
,
],
)
export class CoreModule
【问题讨论】:
这只是一个设计糟糕的API,所以你需要写new HttpResponse( headers: new HttpHeaders(...), ...)
。此类 API 的设计者应该受到谴责。
@AluanHaddad 是的,headers: new HttpHeaders(nativeHttpResponse.headers)
通过了 TS 检查。谢谢
【参考方案1】:
Angular 的 HttpRequest
有一个设计笨拙的 API。具体来说,它的构造函数需要 Angular 的 HttpHeaders
的实例,而不是接受标头对象。
因此,在您的情况下,正确的代码是
const response = new HttpResponse(
body,
status: nativeHttpResponse.status,
headers: new HttpHeaders(nativeHttpResponse.headers),
url: nativeHttpResponse.url
);
我认为这是糟糕的 API 设计简单明了。它偏离了常用的对应API,例如fetch
,增加了耦合,并且不是远程惯用的,同时迫使您编写样板。相比之下,Ionic Native 团队采用了正确的方法,将标头指定为对象。
【讨论】:
以上是关于实现 ionic 的本机 HTTP 拦截器时出现打字稿错误的主要内容,如果未能解决你的问题,请参考以下文章
将工作 Web 应用程序转变为适用于 Android 的本机 Ionic 应用程序时出现 CORS 问题
Angular 6 - Ionic - 使用拦截器中断 http 请求并返回 json
Ionic 3 出现错误 - 本机:尝试调用 HTTP.setSSLCertMode,但未安装 HTTP 插件