0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

核心功能具體的執(zhí)行過(guò)程-2

汽車電子技術(shù) ? 來(lái)源:知碼前端 ? 作者:清清玄 ? 2023-03-01 09:59 ? 次閱讀

前言

上一節(jié)我們簡(jiǎn)單的介紹了一下 axios 的整體加載流程和使用過(guò)程??梢郧宄牧私獾疆?dāng) import axios from 'axios' 之后 這背后到底做了什么。并且我們也簡(jiǎn)單介紹了一個(gè) axios 到底是一個(gè)什么類型的數(shù)據(jù)。以及為什么可以即可以當(dāng)成方法調(diào)用還可以通過(guò)對(duì)象的調(diào)用方式調(diào)用某些屬性方法

如果沒(méi)有了解的同學(xué)可以先去看一下上一篇文章的介紹,再來(lái)繼續(xù)往下看。


這篇我們主要講解一下 axios 中的 配置、攔截器和執(zhí)行鏈等一些核心的功能到底是怎么運(yùn)行的。

02

配置過(guò)程

要了解這個(gè)之前,我們先來(lái)看一下 axios 在使用的時(shí)候一種方式:

axios.create({ ...配置項(xiàng) })

不知道大家有沒(méi)有使用過(guò)種方式,這種方式可以讓我們傳遞一些配置到 axios 的內(nèi)部,具體實(shí)現(xiàn)如下:

axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

沒(méi)錯(cuò),最終又調(diào)用了 createInstance 函數(shù),再來(lái)看一下函數(shù)體吧:

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

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  utils.extend(instance, context);

  return instance;
}

有一個(gè)函數(shù)需要關(guān)注一下就是 mergeConfig, 這個(gè)函數(shù)會(huì)把 axios 自帶的配置和我們傳入的配置進(jìn)行合并,我們傳入的配置會(huì)覆蓋 axios 自帶的配置,也就是說(shuō)我們傳入的配置優(yōu)先級(jí)會(huì)更高。

由于這個(gè) mergeConfig 函數(shù)體太大,我們就不細(xì)說(shuō)了,大家有興趣可以看一下源碼。

這里要繼續(xù)說(shuō)一下,我們?cè)诎l(fā)送某個(gè)具體的請(qǐng)求的時(shí)候也可以進(jìn)行配置,這樣就有三個(gè)配置。

優(yōu)先級(jí)依次是:某個(gè)具體請(qǐng)求配置 > 創(chuàng)建實(shí)例對(duì)象配置 > axios 默認(rèn)配置

03

上節(jié)說(shuō)過(guò),axios可以像對(duì)象那樣調(diào)用屬性方法,如 get、post等,其實(shí)最終都會(huì)調(diào)用 request 方法,代碼如下:

utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: (config || {}).data
    }));
  };
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

可以看出最終都會(huì)調(diào)用到 this.request 方法。那我們來(lái)重點(diǎn)看一下 request方法具體做了什么。

先看一下函數(shù)體吧,代碼也不是很多:

Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = arguments[1] || {};
    config.url = arguments[0];
  } else {
    config = config || {};
  }

  config = mergeConfig(this.defaults, config);

  // Set config.method
  if (config.method) {
    config.method = config.method.toLowerCase();
  } else if (this.defaults.method) {
    config.method = this.defaults.method.toLowerCase();
  } else {
    config.method = 'get';
  }

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

主要有三點(diǎn):

1、生成配置項(xiàng)

2、生成攔截器、執(zhí)行鏈

3、返回執(zhí)行鏈的結(jié)果

下面我們重點(diǎn)介紹一下 2 是如何生成攔截器和執(zhí)行鏈的

每個(gè)axios實(shí)例都會(huì)有一個(gè) interceptors 屬性,如下:

function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

interceptors里面存放著 request 攔截器和response攔截器。InterceptorManager 中有一個(gè) handlers 屬性,是一個(gè)數(shù)組存放著具體的攔截器,再來(lái)看一個(gè)比較熟悉的方法:

InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected
  });
  return this.handlers.length - 1;
};

相信大家肯定用過(guò)這個(gè) use 方法,這個(gè)方法接收兩個(gè)函數(shù)類型的參數(shù),再封裝成一個(gè)對(duì)象放到 handlers中。
再回到 request 函數(shù)體中,看一下

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
      chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

通過(guò)遍歷把 handlers 的攔截器都放到一個(gè) chain 中,尤其要注意:this.interceptors.request 這個(gè)操作,是把最后的攔截器放到 chain的最前面。最終形成以下鏈接:

poYBAGP-sDKAOH_5AADszCSjWMI370.png

當(dāng)然這還不是最終的 chain,因?yàn)榍懊?/span>

var chain = [dispatchRequest, undefined];

有這樣行代碼,所以最終的 chain 應(yīng)該是下面的:

poYBAGP-sDyAKYAzAAEKkVnDApk539.png

這才是一個(gè)最終的 chain 。也就是說(shuō)我們執(zhí)行的每個(gè)請(qǐng)求都是執(zhí)行了一個(gè)鏈,最終返回了一個(gè) promise對(duì)象,是不是感覺(jué)也沒(méi)有那么神秘,看一下執(zhí)行代碼,很簡(jiǎn)單

varpromise=Promise.resolve(config);
while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }
return promise;

以上便是 axios 發(fā)送某個(gè)請(qǐng)求的全過(guò)程,那么接下來(lái)我們繼續(xù)看一下到底是怎么發(fā)送的請(qǐng)求。

04

具體請(qǐng)求

從上面我們可以看到axios發(fā)送的請(qǐng)求就是一個(gè)鏈的執(zhí)行過(guò)程,除去 request 和 response的攔截器不說(shuō),我們重點(diǎn)說(shuō)一下:dispatchRequest 這個(gè)方法的執(zhí)行過(guò)程,因?yàn)榫唧w的請(qǐng)求就是在這個(gè)方法中執(zhí)行的。先來(lái)看一下源碼:

module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);

  // Ensure headers exist
  config.headers = config.headers || {};

  // Transform request data
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers
  );

  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  var adapter = config.adapter || defaults.adapter;

  return adapter(config).then(function onAdapterResolution(response) {
    throwIfCancellationRequested(config);

    // Transform response data
    response.data = transformData(
      response.data,
      response.headers,
      config.transformResponse
    );

    return response;
  }, function onAdapterRejection(reason) {
    if (!isCancel(reason)) {
      throwIfCancellationRequested(config);

      // Transform response data
      if (reason && reason.response) {
        reason.response.data = transformData(
          reason.response.data,
          reason.response.headers,
          config.transformResponse
        );
      }
    }

    return Promise.reject(reason);
  });
};

方法本身并不難理解,處理一下請(qǐng)求頭然后再通過(guò)轉(zhuǎn)換器轉(zhuǎn)一下請(qǐng)求數(shù)據(jù),最后通過(guò)一個(gè)適配器執(zhí)行請(qǐng)求。下面我們?cè)倏匆幌逻m配器是什么,看一下下面的代碼

  var adapter = config.adapter || defaults.adapter;

適配器是通過(guò)配置獲取的,平時(shí)的開發(fā)中我們幾乎不需要自己定義適配器,一般都是用系統(tǒng)默認(rèn)的,所以我們看一下默認(rèn)的適配器是怎么樣的。下面是默認(rèn)配置的代碼:

adapter: getDefaultAdapter(),

繼續(xù)看:

function getDefaultAdapter() {  var adapter;
  if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
    // For node use HTTP adapter
    adapter = require('./adapters/http');
  }
  return adapter;
}

看到這里應(yīng)該大體的有點(diǎn)明白了吧,其實(shí)就是我們平時(shí)用的 XMLHttpRequest 對(duì)象,那為什么還要做一個(gè)適配器呢,主要是因?yàn)?axios 不僅僅是一款可以用在 瀏覽器的庫(kù),在 node 開發(fā)中也可以使用,但node中沒(méi)有 XMLHttpRequest對(duì)象,就得通過(guò)其它的方式實(shí)現(xiàn)。本文不涉及 node,所以我們主要看以下代碼

adapter=require('./adapters/xhr');

因?yàn)榇a比較多,所以這里我用圖片的形式展示一下:

pYYBAGP-sHmAU4Q7AAGPpBiaU2A722.png

到這里,我們才真正看到了熟悉的 XMLHttpRequest對(duì)象。其實(shí)axios底層也就是用的 XMLHttpRequest對(duì)象而已,沒(méi)有什么神秘的。只不過(guò)人家封裝的很好用起來(lái)方便。

其實(shí)到這里我們就已經(jīng)把 axios的整體源碼分析了一次,當(dāng)然還有很多細(xì)節(jié)沒(méi)有說(shuō)到,比如:錯(cuò)誤處理,狀態(tài)碼處理等,大家有興趣的可以自己去細(xì)讀源碼。只有自己閱讀一次才能更好的理解 axios的優(yōu)雅之處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 核心
    +關(guān)注

    關(guān)注

    0

    文章

    44

    瀏覽量

    15028
  • 執(zhí)行
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    12602
  • 配置
    +關(guān)注

    關(guān)注

    1

    文章

    188

    瀏覽量

    18384
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    5G電視或成下代5G無(wú)線通信服務(wù)核心功能

    電視以及視訊內(nèi)容可能會(huì)成為下一代5G無(wú)線通信服務(wù)的核心功能。..
    發(fā)表于 02-17 08:14 ?1383次閱讀

    阿里云數(shù)據(jù)庫(kù)POLARDB核心功能物理復(fù)制技術(shù)解讀

    深入解讀阿里云數(shù)據(jù)庫(kù)POLARDB核心功能物理復(fù)制技術(shù)
    發(fā)表于 06-02 10:16

    智能數(shù)字鐘的核心功能定位

    目錄前言… 2第一章 需求定義… 10產(chǎn)品功能定義… 10智能數(shù)字鐘的核心功能定位… 14芯片選型… 15基于成本約束的設(shè)計(jì)思路… 15CPU的選型… 15音樂(lè)芯片的選型… 16天氣預(yù)報(bào)語(yǔ)音播報(bào)芯片
    發(fā)表于 07-30 07:19

    F103的功能分類核心功能是什么

    文章目錄F103的功能分類核心功能:缺一不可,缺少任何一個(gè)都不能工作。重要功能:根據(jù)每一款單片機(jī)的不同,具有不同的偏重點(diǎn)。多為幫助內(nèi)核做一些內(nèi)核不能做的事情。通信功能:?jiǎn)纹瑱C(jī)行業(yè)成熟,
    發(fā)表于 12-10 07:33

    Bifrost GPU可編程核心的頂級(jí)布局、優(yōu)勢(shì)和著色器核心功能

    本指南介紹了典型的馬里Bifrost GPU可編程核心(第三代馬里GPU)的頂級(jí)布局、優(yōu)勢(shì)和著色器核心功能。Bifrost家族包括Mali-G30、Mali-G50和Mali-G70系列產(chǎn)品。 在
    發(fā)表于 08-02 17:52

    江智機(jī)器人人機(jī)語(yǔ)音交互技術(shù)核心功能點(diǎn)探索

    江智機(jī)器人人機(jī)語(yǔ)音交互技術(shù)核心功能點(diǎn)探索無(wú)疑機(jī)器人人機(jī)語(yǔ)音交互技能是人工智能機(jī)器人必須具有的核心功能點(diǎn)之一。國(guó)內(nèi)的科大訊飛,百度等為代表的一些已在人機(jī)語(yǔ)音技術(shù)方面耕耘了多年,且取得了較大的發(fā)展。國(guó)內(nèi)
    的頭像 發(fā)表于 03-06 14:51 ?897次閱讀
    江智機(jī)器人人機(jī)語(yǔ)音交互技術(shù)<b class='flag-5'>核心功能</b>點(diǎn)探索

    機(jī)器視覺(jué)的四大核心功能

    機(jī)器視覺(jué)的四大核心功能? 機(jī)器視覺(jué)是一種通過(guò)電子系統(tǒng)和計(jì)算機(jī)軟件實(shí)現(xiàn)人類視覺(jué)功能的技術(shù)。它運(yùn)用計(jì)算機(jī)視覺(jué)、模式識(shí)別、圖像處理和機(jī)器學(xué)習(xí)等技術(shù),以攝像機(jī)和圖像處理技術(shù)為基礎(chǔ),將圖像轉(zhuǎn)化為數(shù)字信號(hào),并
    的頭像 發(fā)表于 12-25 11:15 ?1034次閱讀

    智慧灌區(qū)平臺(tái)功能全面解析(智慧灌區(qū)場(chǎng)景和核心功能

    全面解析。() 一、智慧灌區(qū)平臺(tái)業(yè)務(wù)場(chǎng)景和核心功能 智慧灌區(qū)平臺(tái)主要業(yè)務(wù)應(yīng)用于水資源規(guī)劃、相關(guān)設(shè)備監(jiān)管、灌區(qū)用水計(jì)劃、耕地土壤增減方面。其核心功能包括在灌區(qū)區(qū)域部署傳感器設(shè)備對(duì)水文、土壤等信息實(shí)時(shí)采集,然后上傳到云平
    的頭像 發(fā)表于 02-22 10:27 ?636次閱讀
    智慧灌區(qū)平臺(tái)<b class='flag-5'>功能</b>全面解析(智慧灌區(qū)場(chǎng)景和<b class='flag-5'>核心功能</b>)

    [天拓四方]工業(yè)邊緣網(wǎng)關(guān)的核心功能、應(yīng)用場(chǎng)景和實(shí)施策略

    重要支持。本文將重點(diǎn)介紹工業(yè)邊緣網(wǎng)關(guān)的核心功能、應(yīng)用場(chǎng)景和實(shí)施策略,以展示其在工業(yè)自動(dòng)化領(lǐng)域的專業(yè)性和實(shí)用性。 一、工業(yè)邊緣網(wǎng)關(guān)的核心功能 工業(yè)邊緣網(wǎng)關(guān)的核心功能包括: 數(shù)據(jù)采集與集成:邊緣網(wǎng)關(guān)能夠?qū)崟r(shí)采集來(lái)自各種工業(yè)設(shè)
    的頭像 發(fā)表于 05-23 16:29 ?371次閱讀

    深度解析:藍(lán)牙網(wǎng)關(guān)核心功能以及應(yīng)用場(chǎng)景

    為可通過(guò)互聯(lián)網(wǎng)傳輸?shù)臄?shù)據(jù)格式,從而使得遠(yuǎn)程監(jiān)控、數(shù)據(jù)分析和設(shè)備控制成為可能。 二、藍(lán)牙網(wǎng)關(guān)的核心功能 藍(lán)牙網(wǎng)關(guān)的核心功能主要圍繞以下幾個(gè)方面展開: 掃描與連接 :自動(dòng)搜索并連接周圍的藍(lán)牙設(shè)備,無(wú)論是藍(lán)牙低功耗(BLE)設(shè)備還
    的頭像 發(fā)表于 07-10 10:16 ?872次閱讀
    深度解析:藍(lán)牙網(wǎng)關(guān)<b class='flag-5'>核心功能</b>以及應(yīng)用場(chǎng)景

    萬(wàn)界星空科技低代碼云mes核心功能詳解!建議收藏!

    云MES系統(tǒng)作為數(shù)字化轉(zhuǎn)型的關(guān)鍵組成部分,具有一系列核心功能和優(yōu)勢(shì),可以極大地改善制造流程管理和生產(chǎn)執(zhí)行效率。
    的頭像 發(fā)表于 08-06 09:34 ?246次閱讀
    萬(wàn)界星空科技低代碼云mes<b class='flag-5'>核心功能</b>詳解!建議收藏!

    光伏電站智能運(yùn)維管理系統(tǒng)三大核心功能

    光伏電站智能運(yùn)維管理系統(tǒng)三大核心功能 以往,光伏電站的運(yùn)維工作需要人工巡檢和維護(hù),不僅費(fèi)時(shí)費(fèi)力,而且效率低下。而隨著智能技術(shù)的發(fā)展,陜西公眾智能監(jiān)測(cè)自主研發(fā)了光伏電站智能運(yùn)維管理系統(tǒng),為光伏電站運(yùn)維
    的頭像 發(fā)表于 08-23 15:55 ?426次閱讀
    光伏電站智能運(yùn)維管理系統(tǒng)三大<b class='flag-5'>核心功能</b>

    PCS儲(chǔ)能變流器工作原理與核心功能

    PCS儲(chǔ)能變流器是一種雙向電流可控轉(zhuǎn)換裝置,它能夠連接儲(chǔ)能電池系統(tǒng)與電網(wǎng)或負(fù)荷。這種裝置的核心功能是控制儲(chǔ)能電池的充電和放電過(guò)程,實(shí)現(xiàn)交直流電能的變換。在無(wú)電網(wǎng)情況下,PCS儲(chǔ)能變流器甚至可以直接為
    的頭像 發(fā)表于 09-17 17:03 ?1036次閱讀

    工業(yè)物聯(lián)網(wǎng)盒子核心功能與技術(shù)特點(diǎn)

    將這些數(shù)據(jù)上傳至云端或本地服務(wù)器進(jìn)行分析處理。工業(yè)物聯(lián)網(wǎng)盒子不僅是數(shù)據(jù)采集的前端,也是實(shí)現(xiàn)設(shè)備遠(yuǎn)程監(jiān)控、預(yù)測(cè)性維護(hù)、能效優(yōu)化等高級(jí)應(yīng)用的基礎(chǔ)。 一、核心功能與技術(shù)特點(diǎn) 工業(yè)物聯(lián)網(wǎng)盒子的核心功能與技術(shù)特點(diǎn),使其能
    的頭像 發(fā)表于 11-22 17:21 ?221次閱讀

    Monitor Wafer的核心功能、特點(diǎn)、生產(chǎn)流程和應(yīng)用

    制造中扮演著至關(guān)重要的角色。它并不直接用于最終產(chǎn)品的制造,而是作為一種過(guò)程監(jiān)控工具,用于實(shí)時(shí)或周期性地“診斷”設(shè)備和工藝的健康狀況,確保整個(gè)生產(chǎn)流程的穩(wěn)定性和可靠性。 一、Monitor Wafer的核心功能
    的頭像 發(fā)表于 12-06 10:59 ?317次閱讀