欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

axios對外出口API的設計方法

 更新時間:2024年05月06日 09:16:34   作者:zhangbao90s  
本文我們講解了 axios 對外出口 API 是如何設計的,我們首先介紹了內部 Axios 類的實現(xiàn),這是 axios 核心邏輯所在,其次為了讓出口 API 更好使用,最后又在增加了 create() 方法,文中通過代碼示例講解的非常詳細,需要的朋友可以參考下

本文我們將討論 axios 對外出口 API 是如何設計的。

axios 的 2 種使用方式

當通過 npm install axios 安裝完 axios 之后,就可以以下 2 種方式使用 axios。

一種是在請求時傳入 axios 配置項。

// GET 請求
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .finally(function () {
    // always executed
  });
  
// POST 請求
axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

還有一種,就是通過 axios.create() 創(chuàng)建一個包含預配置的 axios,再進行請求。

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

axios.get('/user')
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'})

這樣就避免了每個請求中總是重復書寫相同配置的苦惱。

請求方法別名

在實際項目中使用 axios 請求時,我們通過會使用 axios.method() 的方式發(fā)送請求。這樣的方法一共有 8 個:

  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])
  • axios(config)

這 8 個請求方法,底層都是基于 axios.request(config) 封裝的。

其中:

  • axios(config) 是 axios.request(config) 的別名
  • axios.get、axios.delete、axios.head、axios.options(url[, config]) 類似于 axios.request({ ...config, method, url, data: config?.data })
  • axios.post、axios.put、axios.patch(url[, data[, config]]) 類似于 axios.request({ ...config, method, url, data })

了解了這些請求方法別名后,我們就來看它們的底層實現(xiàn)。

Axios 類

axios 其實是內部 Axios 類的實例。Axios 類的源碼位于 lib/core/Axios.js。

其總體實現(xiàn)如下:

// /v1.6.8/lib/core/Axios.js
class Axios {
  // 1)
  constructor(instanceConfig) {
    this.defaults = instanceConfig;
    this.interceptors = {
      request: new InterceptorManager(),
      response: new InterceptorManager()
    };
  }
  
  // 2)
  async request(configOrUrl, config) {/* ... */}
  
  // 3)
  getUri(config) {/* ... */}
}

// 3)
['delete', 'get', 'head', 'options'].forEach(function forEachMethodNoData(method) {/* ... */})
['post', 'put', 'patch'].forEach(function forEachMethodNoData(method) {/* ... */})

1):可以看到,Axios 類的實現(xiàn)代碼還是比較少的,就 2 個方法:

  • async request() 就對應前面所說的 axios.request(),是所有請求的入口地方
  • getUri() 比較少用,是用來獲得完整請求路徑(基于當前 axios 的默認配置和你傳入的配置)

2):另外,在創(chuàng)建 Axios 實例時,實例對象上會綁定 defaults、interceptors 屬性。

  • defaults 是在創(chuàng)建 Axios 實例傳入的配置,作為默認配置用
  • interceptors 則是攔截器配置入口,如果你設置過攔截器,肯定知道它

3):最后這部分的代碼,其實就是基于 Axios.prototype.request 方法進行封裝,分別在 Axios.prototype 上添加 'delete'、'get'、'head'、'options' 和 'post'、'put'、'patch' 方法,前 4 個是一類,后 3 個是一類。

接下來,我們詳細說一下。

Axios.prototype.request()

這是 axios 實現(xiàn)核心請求邏輯的方法。

為了避免贅述,我這里給出偽代碼實現(xiàn)。

async request(configOrUrl, config) {
  // 獲得傳入的配置
  config = getFinalConfigBy(configOrUrl, config)
  
  // 與內部默認配置合并
  config = mergeConfig(this.defaults, config);
  
  // 拼裝完整請求鏈
  const chain = []
    .concat(requestInterceptorChain)
    .concat(dispatchRequest)
    .concat(responseInterceptorChain)
  
  // 發(fā)起并返回請求結果
  return request(chain)
}

axios.defaults/interceptors

這是 Axios 實例上的兩個屬性。

axios.defaults 允許你做默認配置的修改,會對所有當前 axios 實例的請求都生效。

axios.interceptors 則用來提供配置請求/響應攔截器。interceptors.request 允許你在請求前修改請求配置,interceptors.response 則允許你在請求得到響應后、交由用戶處理前,提前統(tǒng)一對響應數(shù)據(jù)做處理。

request、response 2 個屬性都是 InterceptorManager 實例,提供 use()/eject()/clear()(對外) 方法和 forEach()(對內)方法。

有興趣的想要了解攔截器實現(xiàn)機制的讀者,可以瀏覽之前的《axios 攔截器機制是如何實現(xiàn)的?》 一文進行學習。

請求方法別名

再來看看請求方法別名的實現(xiàn)。

先看 'delete'、'get'、'head'、'options' 這 4 個方法。

// /v1.6.8/lib/core/Axios.js#L193-L202
['delete', 'get', 'head', 'options'].forEach(function forEachMethodNoData(method) {
  Axios.prototype[method] = function(url, config) {
    return this.request(mergeConfig(config || {}, {
      method,
      url,
      data: (config || {}).data
    }));
  };
});

實現(xiàn)稍稍簡單。本質上就是為 Axios.prototype 分別添加以上述 4 種請求方式為名的請求實現(xiàn)。this.request() 就是 Axios.prototype.request() 方法。

以 axios.delete(url, config) 為例:'delete' 作為 config.method,url 作為 config.url,最后和傳入的 config 合并成一個,交由 axios.request() 處理。

再來看看 'post'、'put'、'patch' 這 3 個方法的實現(xiàn)。

// /v1.6.8/lib/core/Axios.js#L204-L223
['post', 'put', 'patch'].forEach(function forEachMethodWithData(method) {
  function generateHTTPMethod(isForm) {
    return function httpMethod(url, data, config) {
      return this.request(mergeConfig(config || {}, {
        method,
        headers: isForm ? {
          'Content-Type': 'multipart/form-data'
        } : {},
        url,
        data
      }));
    };
  }

  Axios.prototype[method] = generateHTTPMethod();
  Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
});

會稍稍復雜一丟丟。因為 axios 還額外支持了 'postForm'、'putForm'、'patchForm' 3 個方法,用于傳輸文件的場景。

以 axios.post(url, data, config) 為例:'post' 作為 config.method,url 作為 config.url,data 作為 config.data,最后和傳入的 config 合并成一個,交由 axios.request() 處理。

以 axios.postForm(url, data, config) 為例,相比 axios.post(url, data, config),多傳入了一個 'Content-Type': 'multipart/form-data' 的請求頭配置。這個請求頭項會幫助后端理解要處理的請求類型。

導出 axios

以上我們介紹了 Axios 類的邏輯實現(xiàn)。

如果直接導出 Axios

不過,如果只導出 Axios 類作為對外輸出,那么使用方式就是下面這樣。

//////
// axios.js
//////

export { default as defaults } from './defaults/index.js';
export default Axios;

////// 
// app.js
//////

import Axios, { defaults } from 'axios'
// 使用方式一
new Axios(defaults).get('/user')
new Axios(defaults).post('/user', {firstName: 'Fred',lastName: 'Flintstone'})
// 使用方式二
const createAxios = () {
  return new Axios(defaults) 
}
const axios = createAxios()
axios.get('/user')
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'})

new Axios() 創(chuàng)建實例的方式不夠優(yōu)雅,而且每次使用都會有一段樣板代碼。

為了減少這部分的工作,axios 團隊在導出時針對 Axios 做了一層封裝,讓導出 API 更加好用。源碼位于 lib/axios.js。

// /v1.6.8/lib/axios.js#L28-L44
function createInstance(defaultConfig) {
  // 1.1)
  const context = new Axios(defaultConfig);
  const instance = Axios.prototype.request.bind(context);

  // 2)
  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context, {allOwnKeys: true});
  // Copy context to instance
  utils.extend(instance, context, null, {allOwnKeys: true});

  // 3)
  // Factory for creating new instances
  instance.create = function create(instanceConfig) {
    return createInstance(mergeConfig(defaultConfig, instanceConfig));
  };
  
  // 1.2)
  return instance;
}

// 1)
// Create the default instance to be exported
const axios = createInstance(defaults);

// this module should only have a default export
export default axios

1)、首先,導出的 axios 其實是 createInstance(defaults) 的返回值

參數(shù) defaults 是 axios 內部默認配置信息。

import defaults from './defaults/index.js';

而 createInstance() 內部,返回的其實并不是 Axios 實例,而是 Axios 實例的 request() 方法。

function createInstance(defaultConfig) {
  // 返回的并不是 Axios 實例
  const context = new Axios(defaultConfig);
  // 而是 Axios 實例的 request() 方法
  const instance = Axios.prototype.request.bind(context);
  
  // ...
  
  return instance;
}

這樣,我們就能以 axios(config) 方式發(fā)起請求,沒必要寫成 axios.request(config) 這樣了。

同時值得注意的時,request() 方法內部的 this 綁定到了 Axios 實例(即 context)上。這樣,request() 方法內部訪問的 this 時就不會有問題了。

2)、不過 instance(也就是 axios.request)上現(xiàn)在是沒有 Axios 實例上的其他方法了!

因此,接下來我們把 Axios.prototype 和 context 上的屬性都復制給 instance。

function createInstance(defaultConfig) {
  const context = new Axios(defaultConfig);
  const instance = Axios.prototype.request.bind(context);

  // 把 Axios.prototype 上的屬性都復制給 instance
  utils.extend(instance, Axios.prototype, context, {allOwnKeys: true});
  // 把 context 上的屬性都復制給 instance
  utils.extend(instance, context, null, {allOwnKeys: true});

  // ...
  
  return instance;
}

如此一來,我們就能在 instance 上調用 get()/post()/getUri() 等這些方法了。

3)另外,在來實現(xiàn) axios.create()

function createInstance(defaultConfig) {
  // ...
  
  // 基于內部默認配置,在創(chuàng)建一個新的 Axios 實例
  instance.create = function create(instanceConfig) {
    return createInstance(mergeConfig(defaultConfig, instanceConfig));
  };
  
  return instance;
}

可以看到 instance.create 手動增加了 create() 方法。

create() 方法內部其實就是遞歸調用 createInstance()。不同的是,instance.create() 本質上是基于導出的 axios 的基礎上再多一步自定義配置合并。

總結

本文我們講解了 axios 對外出口 API 是如何設計的。

我們首先介紹了內部 Axios 類的實現(xiàn),這是 axios 核心邏輯所在;其次為了讓出口 API 更好使用,真正導出的 axios 其實是 Axios 實例的 request() 方法,最后又在增加了 create() 方法,方便進一步得到擁有自定義配置的 axios 對象。

以上就是axios對外出口API的設計方法的詳細內容,更多關于axios對外出口API的資料請關注腳本之家其它相關文章!

相關文章

最新評論