# 1. 前言 在上一篇文章中,我们实现了axios的请求和响应拦截器功能,并且为它们编写了对应的测试用例。接下来,我们就来实现axios的配置化,所谓配置化是指:我们希望能够对每次请求的配置进行设定,设定一些公共的默认配置,并且还可以在每次请求中自定义配置,并且自定义配置优先级高于默认配置。 # 2. 需求分析 我们希望axios可以有默认配置,并且还可以在每次请求中传入自定义配置,自定义配置可以覆盖默认配置,并且希望默认配置和自定义配置可以合并。如下: typescript // 默认配置 axios.defaults.headers.common["test"] = 1; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; // 自定义配置 const instance = axios.create({ headers: { test: 2, }, }); instance.get("/more/get", { headers: { test: 3, }, }); 对于headers这类复杂对象属性,我们需要进行深拷贝,同时也处理了其它一些情况,如下: typescript axios.defaults.baseURL = "https://api.example.com"; // 默认配置 axios.defaults.headers.common["test"] = 1; // 自定义配置 const instance = axios.create({ baseURL: "https://img.example.com", headers: { test: 2, }, }); instance.get("/more/get", { headers: { test: 3, }, }); 合并后的配置应该是: json { "baseURL": "https://img.example.com", "headers": { "common": { "test": 1 }, "test": 3 } } # 3. 默认配置 首先,我们先来实现默认配置。默认配置我们可以在src/axios.ts中定义,如下: typescript // src/axios.ts const defaults: AxiosRequestConfig = { timeout: 0, headers: { common: { Accept: "application/json, text/plain, */*", }, }, }; const methodsNoData = ["delete", "get", "head", "options"]; methodsNoData.forEach((method) => { defaults.headers[method] = {}; }); const methodsWithData = ["post", "put", "patch"]; methodsWithData.forEach((method) => { defaults.headers[method] = { "Content-Type": "application/x-www-form-urlencoded", }; }); 我们定义了defaults常量,它包含默认配置。对于headers,我们定义了common和一些请求方法的headers,common表示对于任何类型的请求都要添加该header,而对于get、post等方法,也会添加对应的header,但是会覆盖common中相同的header。 # 4. 合并策略 合并策略我们采用与axios官方相同的策略,如下: typescript // src/core/mergeConfig.ts import { AxiosRequestConfig } from "./types"; import { deepMerge, isPlainObject } from "./util"; const strats = Object.create(null); function defaultStrat(val1: any, val2: any): any { return typeof val2 !== "undefined" ? val2 : val1; } function fromVal2Strat(val1: any, val2: any): any { if (typeof val2 !== "undefined") { return val2; } } function deepMergeStrat(val1: any, val2: any): any { if (isPlainObject(val2)) { return deepMerge(val1, val2); } else if (typeof val2 !== "undefined") { return val2; } else if (isPlainObject(val1)) { return deepMerge(val1); } else if (typeof val1 !== "undefined") { return val1; } } const stratKeysFromVal2 = ["url", "params", "data"]; stratKeysFromVal2.forEach((key) => { strats[key] = fromVal2Strat; }); const stratKeysDeepMerge = ["headers"]; stratKeysDeepMerge.forEach((key) => { strats[key] = deepMergeStrat; }); export default function mergeConfig( config1: AxiosRequestConfig, config2?: AxiosRequestConfig ): AxiosRequestConfig { if (!config2) { config2 = {}; } const config = Object.create(null); for (let key in config2) { mergeField(key); } for (let key in config1) { if (!config2[key]) { mergeField(key); } } function mergeField(key: string): void { const strat = strats[key] || defaultStrat; config[key] = strat(config1[key], config2![key]); } return config; } 合并规则如下: - 对于url、params、data这些属性,默认使用config2中的配置,即自定义配置。 - 对于headers这类复杂对象,采用深拷贝的方式,并且会合并config1和config2中的配置。 - 对于其他属性,采用默认策略,即如果config2中有配置,则使用config2中的配置,否则使用config1中的配置。 # 5. 修改 axios 函数 接下来,我们需要修改src/axios.ts中的axios函数,让它支持默认配置和自定义配置的合并。 typescript // src/axios.ts import { AxiosRequestConfig, AxiosPromise, Method } from "./types"; import dispatchRequest from "./core/dispatchRequest"; import InterceptorManager from "./core/InterceptorManager"; import mergeConfig from "./core/mergeConfig"; interface Interceptors { request: InterceptorManager
Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Deal anzeigenFolgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Deal anzeigenFolge einfach unserem Link Anschließend kannst du Geschenkgutscheine im Wert von 10 Euro bis 800 Euro bestellen
Deal anzeigenFolgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Deal anzeigenGilt für Fotoshootings Nicht kombinierbar mit anderen Aktionen. Keine Barauszahlung.
Gilt beim Ferien-Special auf ein Mini-Fotoshooting für Kinder & Familien Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Gilt beim Oster-Special auf ein Professionelles Fotoshooting mit Bilderpaket Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.
Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen
Wir schicken dir eine E-Mail, wenn es einen neuen
PicturePeople Gutscheincode gibt!