axios 차단기의 실현

31975 단어

차단기 설계와 실현


# 요구 사항 분석


우리는 요청의 발송과 응답을 차단할 수 있기를 희망한다. 즉, 요청을 보내기 전과 응답을 받은 후에 추가 논리를 할 수 있기를 바란다.
우리가 설계하고자 하는 차단기의 사용 방식은 다음과 같다.
//  
axios.interceptors.request.use(function (config) { //   return config; }, function (error) { //   return Promise.reject(error); }); //   axios.interceptors.response.use(function (response) { //   return response; }, function (error) { //   return Promise.reject(error); }); 
axios 대상에 하나의 interceptors 대상 속성이 있는데 이 속성은 requestresponse 두 개의 속성이 있는데 모두 하나의 use 방법이 있고 use 방법은 2개의 파라미터를 지원하며 첫 번째 파라미터는 Promise의 resolve 함수와 유사하고 두 번째 파라미터는 Promise의 reject 함수와 유사하다.우리는 resolve 함수와 reject 함수에서 동기화 코드나 비동기 코드 논리를 실행할 수 있다.
그리고 우리는 여러 개의 차단기를 추가할 수 있습니다. 차단기의 실행 순서는 체인식으로 순서대로 실행하는 방식입니다.request 차단기에 대해 다음에 추가된 차단기는 요청 전 과정에서 먼저 실행됩니다.response 차단기에 대해 먼저 추가된 차단기는 응답 후에 실행됩니다.
axios.interceptors.request.use(config => { config.headers.test += '1' return config }) axios.interceptors.request.use(config => { config.headers.test += '2' return config }) 

또한 다음과 같은 차단기를 삭제할 수도 있습니다.
const myInterceptor = axios.interceptors.request.use(function () {/*...*/}) axios.interceptors.request.eject(myInterceptor) 

# 전체적인 디자인


우리는 먼저 한 장의 그림으로 차단기 작업 절차를 보여 준다.
전체 과정은 체인식 호출 방식이고 모든 차단기는 동기화와 비동기 처리를 지원할 수 있기 때문에 우리는 자연스럽게Promise 체인을 사용하는 방식으로 전체 호출 과정을 실현하는 것을 연상한다.
이 Promise 체인의 실행 과정에서 요청 차단기resolve 함수 처리는 config 대상이고, 해당 차단기resolve 함수 처리는 response 대상이다.
차단기의 작업 흐름을 이해한 후에, 우리는 삭제와 반복 차단기를 추가할 수 있도록 차단기 관리 클래스를 만들어야 합니다.

# 차단기 관리 클래스 구현


수요에 따라 axios대상속성이 하나 있고 이 속성은 interceptorsrequest2개의 속성이 있다. 그들은 대외적으로 response방법을 제공하여 차단기를 추가한다. 우리는 이 두 속성을 차단기 관리 대상으로 볼 수 있다.use 방법은 2개의 매개 변수를 지원한다. 첫 번째는 use 함수, 두 번째는 resolve 함수이다. reject 함수의 매개 변수에 대해 요청 차단기는 resolve 유형이고 응답 차단기는 AxiosRequestConfig 유형이다.AxiosResponse 함수의 매개 변수 유형은 reject 유형이다.
상술한 분석에 근거하여 우리는 먼저 차단기 관리 대상의 대외 인터페이스를 정의한다.

# 인터페이스 정의

any :
export interface AxiosInterceptorManager<T> { use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number eject(id: number): void } export interface ResolvedFn<T=any> { (val: T): T | Promise<T> } export interface RejectedFn { (error: any): any } 

여기에서 우리는 types/index.ts 범용 인터페이스를 정의했다. 왜냐하면 AxiosInterceptorManager 함수의 매개 변수에 대해 요청 차단기와 응답 차단기는 다르기 때문이다.

# 코드 구현

import { ResolvedFn, RejectedFn } from '../types' interface Interceptor<T> { resolved: ResolvedFn<T> rejected?: RejectedFn } export default class InterceptorManager<T> { private interceptors: Array<T> | null> constructor() { this.interceptors = [] } use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number { this.interceptors.push({ resolved, rejected }) return this.interceptors.length - 1 } forEach(fn: (interceptor: Interceptor<T>) => void): void { this.interceptors.forEach(interceptor => { if (interceptor !== null) { fn(interceptor) } }) } eject(id: number): void { if (this.interceptors[id]) { this.interceptors[id] = null } } } 

우리는 resolve 범용 클래스를 정의했고 내부적으로 개인 속성InterceptorManager을 유지했다. 이것은 차단기를 저장하는 데 사용되는 수조이다.이 종류는 대외적으로 세 가지 방법을 제공했는데 그 중에서 interceptors 인터페이스는 차단기를 use에 추가하고 삭제할 수 있도록 되돌려주는 것이다.interceptors 인터페이스는 역력id에 사용되는 것으로 하나의 함수를 지원하며 역력 과정에서 이 함수를 호출하고 각각forEach을 이 함수의 매개 변수로 전입한다.interceptors는 차단기를 삭제하고 차단기를 전송한 interceptor을 통해 삭제한다.

# 체인 호출 구현


이 소절은 Promise에 대한 파악과 이해가 필요합니다. mdn에 가서 공부할 수 있습니다.
차단기 관리 클래스를 실현하면 eject 에서 id 속성을 정의합니다. 그 유형은 다음과 같습니다.
interface Interceptors {
  request: InterceptorManager> response: InterceptorManager> } export default class Axios { interceptors: Interceptors constructor() { this.interceptors = { request: new InterceptorManager>(), response: new InterceptorManager>() } } } 
Axios 유형은 2개의 속성을 가지고 하나는 요청 차단기 관리 클래스의 실례이고 하나는 응답 차단기 관리 클래스의 실례이다.우리가 실례화interceptors류를 할 때, 그 구조기에서 이 Interceptors 실례 속성을 초기화합니다.
다음은 Axios 방법의 논리를 수정하고 차단기 체인 호출의 논리를 추가합니다.interceptors :
interface PromiseChain {
  resolved: ResolvedFn | ((config: AxiosRequestConfig) => AxiosPromise) rejected?: RejectedFn } request(url: any, config?: any): AxiosPromise { if (typeof url === 'string') { if (!config) { config = {} } config.url = url } else { config = url } const chain: PromiseChain[] = [{ resolved: dispatchRequest, rejected: undefined }] this.interceptors.request.forEach(interceptor => { chain.unshift(interceptor) }) this.interceptors.response.forEach(interceptor => { chain.push(interceptor) }) let promise = Promise.resolve(config) while (chain.length) { const { resolved, rejected } = chain.shift()! promise = promise.then(resolved, rejected) } return promise } 

먼저 request 유형의 수조core/Axios.ts를 구성하고 PromiseChain 함수를 chain 속성에 부여한다.이어서 요청 차단기를 dispatchRequest 앞에 삽입합니다.그리고 응답 차단기를 반복해서 resolved 뒤에 삽입합니다.
다음은 이미resolvechain를 정의하고 이것chain을 순환하여 모든 차단기 대상을 가져와 그것들promise 함수와 chain 함수를 resolved 매개 변수에 추가하면 Promise의 체인 호출 방식을 통해 차단기의 층층이 체인 호출 효과를 실현하는 것과 같다.
우리 차단기의 실행 순서를 주의하십시오. 요청 차단기는 먼저 실행한 후에 추가한 다음에 먼저 추가한 것을 실행합니다.응답 차단기에 대해서는 먼저 추가한 것을 실행하고 나중에 추가한 것을 실행합니다.

#demo 작성

rejected 디렉터리에서 promise.then 디렉터리를 만들고, examples 디렉터리에서 interceptor 디렉터리를 만듭니다.

lang="en"> > charset="utf-8"> >Interceptor example<span class="token tag"><span class="token tag"><span class="token punctuation"/></span></span>> > > src<span class="token attr-value"><span class="token punctuation">=<span class="token punctuation">"/__build__/interceptor.js<span class="token punctuation">"<span class="token punctuation">><span class="token script language-javascript"><span class="token tag"><span class="token tag"><span class="token punctuation">> > > 

다음으로 interceptor 를 포털 파일로 만듭니다.
import axios from '../../src/index'

axios.interceptors.request.use(config => { config.headers.test += '1' return config }) axios.interceptors.request.use(config => { config.headers.test += '2' return config }) axios.interceptors.request.use(config => { config.headers.test += '3' return config }) axios.interceptors.response.use(res => { res.data += '1' return res }) let interceptor = axios.interceptors.response.use(res => { res.data += '2' return res }) axios.interceptors.response.use(res => { res.data += '3' return res }) axios.interceptors.response.eject(interceptor) axios({ url: '/interceptor/get', method: 'get', headers: { test: '' } }).then((res) => { console.log(res.data) }) 

이 데모는 요청 차단기 3개를 추가했습니다. 응답 차단기 3개를 추가하고 두 번째를 삭제했습니다.이 데모를 실행하면 브라우저를 통해 접근합니다. 저희가 보낸 요청에 index.html 요청 헤더를 추가했습니다. 그 값은 app.ts 입니다.우리의 응답 데이터는 test, 응답 차단기의 처리를 거쳐 최종적으로 우리가 출력한 데이터는 321이다.
이로써 우리는 hello 차단기 기능을 실현했다. 이것은 매우 실용적인 기능으로 실제 업무에서 우리는 그것을 이용하여 로그인 권한 인증과 같은 수요를 만들 수 있다.
우리는 현재 hello13 요청을 보내면 종종 한 무더기의 설정이 전송되지만, 우리도 ts-axios 자체에도 일부 기본 설정이 있기를 바란다. 우리는 사용자가 전송한 사용자 정의 설정과 기본 설정을 한 겹으로 통합하기를 바란다.사실 대부분의 JS 라이브러리는 비슷한 방법입니다.다음 장에서 우리는 이 기능을 실현할 것이다.
다음으로 전송:https://www.cnblogs.com/QianDingwei/p/11403923.html

좋은 웹페이지 즐겨찾기