国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

axios源碼閱讀(一)

k00baa / 3519人閱讀

摘要:開始研究核心代碼這個類首先是構(gòu)造函數(shù)看完上面的內(nèi)容大家應(yīng)該有點印象,上掛了和,是默認(rèn)的配置,顧名思義就是攔截器,目測包含了和兩種類型。喜歡就點個贊吧參考文章源代碼重點難點分析源代碼重點難點分析

axios是一個基于promise的http庫,支持瀏覽器和node端,最近我在做beauty-we的api設(shè)計,研讀一個成熟的http庫勢在必行,axios功能完整、api簡潔、注釋清晰,再適合不過,現(xiàn)在就讓我們開始吧~

準(zhǔn)備工作

clone項目,打開dist文件夾,里面有axios.js和axios.min.js,看一下axios.js的第一段:

(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === "object" && typeof module === "object") {
    module.exports = factory();
  } else if (typeof define === "function" && define.amd) {
    define([], factory);
  } else if (typeof exports === "object") {
    exports.axios = factory();
  } else {
    root.axios = factory();
  }
})(this, function() {...我是主代碼部分...});

最外層是一個立即執(zhí)行函數(shù)(IIFE),傳入?yún)?shù)this和構(gòu)造函數(shù)factory,區(qū)分了4種情況:

exports和module都存在時,cmd模式;

define和define.amd都存在時,amd模式;

只有exports存在時;

既不是cmd也不是cmd模式時,掛載在傳入的宿主對象上。

我比較了其他3個類庫的處理(underscore/jquery/vue):

underscore
(function() {
    var root = typeof self == "object" && self.self === self && self ||typeof global == "object" && global.global === global && global ||this ||{};

    if (typeof exports != "undefined" && !exports.nodeType) {
        if (typeof module != "undefined" && !module.nodeType && module.exports) {
            exports = module.exports = _;
        }
        exports._ = _;
      } else {
        root._ = _;
      }

  // ....這里是主代碼部分...
  if (typeof define == "function" && define.amd) {
    define("underscore", [], function() {
      return _;
    });
  }
}());
jquery
(function( global, factory ) {
if ( typeof module === "object" && typeof module.exports === "object" ) {
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }
if ( typeof define === "function" && define.amd ) {
    define( "jquery", [], function() {
        return jQuery;
    } );
}

})(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
    // ...這里是主代碼部分
})
vue
(function (global, factory) {
    typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() :
    typeof define === "function" && define.amd ? define(factory) :
    (global.Vue = factory());
}(this, (function () {
    // ...這里是主代碼部分...
}))

4個庫中,

underscore和axios考慮了4種環(huán)境情況,vue和jquery無視了exports存在但沒有module的情況(這種情況什么時候出現(xiàn)我不清楚,知道的人求指出);環(huán)境判斷vue用了3目運算符,看起來又干凈又漂亮(其實這好像并不重要,壓縮后大家都一樣~);對amd的支持underscore和jquery都放在了代碼的尾部,打補丁的痕跡好明顯;

jquery強調(diào)了document一定存在,否則會拋出錯誤,axios和vue只是傳入了this,underscore則認(rèn)真區(qū)分了browser的window,server端的global,其他端的this,自創(chuàng)了一個self統(tǒng)一之,這意味著后三者可以存活在更普遍的環(huán)境中(比如axios in web worker,比如weex),underscore的做法最嚴(yán)謹(jǐn);

除了underscore,其他3者都把主代碼放在了IIFE的參數(shù)里,而underscore是直接寫在IIFE里,我個人還是喜歡用那個叫factory的函數(shù)。

看整體

啰嗦了那么多之后,正式開始看axios啦。根據(jù)package.json里的npm run dev的指向,我們打開lib文件夾里的axios.js,這就是全局入口了。

./lib/axios.js只做了兩件事:

創(chuàng)建一個axios對象

暴露一些拓展方法出去

先看axios對象的創(chuàng)建:

var axios = createInstance(defaults);

function createInstance(defaultConfig) {
  // 一切的開始,new一個實例出來
  var context = new Axios(defaultConfig);

  var instance = bind(Axios.prototype.request, context);

  utils.extend(instance, Axios.prototype, context);

  utils.extend(instance, context);

  return instance;
}

創(chuàng)建實例axios用了4步,第2步開始就比較奇怪了:

var instance = bind(Axios.prototype.request, context);

看一下bind函數(shù):

function bind(fn, thisArg) {
  return function wrap() {
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
    return fn.apply(thisArg, args);
  };
}

它返回一個wrap()函數(shù),其中執(zhí)行了參數(shù)1的函數(shù),綁定了參數(shù)2的上下文,也就是說,instance是一個叫wrap的函數(shù),它里面執(zhí)行了Axios原型對象上的request方法,同時綁定了最開始創(chuàng)建的那個實例的上下文;
再看下一行:

utils.extend(instance, Axios.prototype, context);

看一下extend函數(shù):

function extend(a, b, thisArg) {
  forEach(b, function assignValue(val, key) {
    if (thisArg && typeof val === "function") {
      a[key] = bind(val, thisArg);
    } else {
      a[key] = val;
    }
  });
  return a;
}

它承擔(dān)了兩個任務(wù),當(dāng)參數(shù)3存在時,它循環(huán)參數(shù)2,把參數(shù)2 上的屬性是函數(shù)類型的都用bind的方式掛載到參數(shù)1身上;否則的話,它實現(xiàn)了簡單的把參數(shù)2的復(fù)制給參數(shù)1;
那么看最后一行就知道了,3-4實現(xiàn)的是把Axios原型上的函數(shù)屬性都掛載到instance,這是第2行的一個循環(huán)版本,最后把axios實例復(fù)制給instance,形成一個真正的instance,此時,這個instance具備Axios實例的靜態(tài)屬性(復(fù)制來的),Axios.prototype上所有函數(shù)方法(通過bind,返回一個wrap(),里面調(diào)用Axios.prototype上的方法),instance本身還是一個wrap版本的Axios.prototype.request方法。
這時我好想問一個:為什么這么做。。
思考好久找到突破口,就是最奇怪的最后一點,axios是一個wrap函數(shù),包含了request,這其實是因為axios支持的兩種調(diào)用方式:
axios({config}).then()axios.get("url").then()
前者確定了axios自身作為一個函數(shù)的特性,同時,它還需要具有g(shù)et/post等一堆方法,于是我翻到的commit最初的版本是:

var defaultInstance = new Axios();

var axios = module.exports = bind(Axios.prototype.request, defaultInstance);

這里還少了把defaultInstance上的靜態(tài)屬性復(fù)制給axios的過程,當(dāng)時Axios上的靜態(tài)屬性還很少,只有defaults,被手動掛載給axios:axios.defaults=defaults;
隨著Axios添加了InterceptorManager攔截器,進(jìn)化成了第二版本:

var defaultInstance = new Axios();

var axios = module.exports = bind(Axios.prototype.request, defaultInstance);

axios.defaults=defaults;
axios.interceptors = defaultInstance.interceptors;

但是有人發(fā)現(xiàn)了一個bug,因為axios自帶create方法,可以自定義一個實例,而create內(nèi)寫的卻是極度簡陋的:

axios.create = function (defaultConfig) {
  return new Axios(defaultConfig);
};

大家發(fā)現(xiàn)axios.create出來的和axios比較后api少很多啊,于是終極版本的構(gòu)建函數(shù)createInstance誕生了:

function createInstance(defaultConfig) {
  // 一切的開始,new一個實例出來,然而考慮到它不是最終對象,只能稱之為上下文
  var context = new Axios(defaultConfig);
// 這是最后返回的實例,本身是一個request函數(shù)
  var instance = bind(Axios.prototype.request, context);
  // 為了拓展性,一口氣把原型對象上所有的方法都拷一份
  utils.extend(instance, Axios.prototype, context);

  // 把實例的靜態(tài)屬性復(fù)制過來
  utils.extend(instance, context);

  return instance;
}

終于創(chuàng)建完axios對象,接下來是暴露一些api出去:

// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
// Expose Axios class to allow class inheritance
axios.Axios = Axios;
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread =function spread(callback) {
  return function wrap(arr) {
    return callback.apply(null, arr);
  };
}
axios.Cancel...
axios.CancelToken...
axios.isCancel...

入口文件的分析就到此結(jié)束了。

core Axios

開始研究核心代碼Axios這個類;
首先是構(gòu)造函數(shù):

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

看完上面的內(nèi)容大家應(yīng)該有點印象,axios上掛了defaults和interceptors,defaults是默認(rèn)的config配置,interceptors顧名思義就是攔截器,目測包含了request和response兩種類型。
接下來看個簡單的部分:

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

axios把7種請求都轉(zhuǎn)向了request方法,根據(jù)是否要帶data寫了2個循環(huán),看起來還挺簡潔的。
接下來看最核心的request代碼,這里的處理很巧妙很優(yōu)雅:

Axios.prototype.request = function request(config) {
    // ...我是很多config處理...此時不關(guān)心

    // 創(chuàng)建了一個事件數(shù)組,第一位的是發(fā)送請求的動作,這是默認(rèn)狀態(tài)
    var chain = [dispatchRequest, undefined];
    // 創(chuàng)建了一個promise對象
  var promise = Promise.resolve(config);
//   循環(huán)request攔截器,有的話就添加到chain的頭部
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });
// 循環(huán)response攔截器,有的話就添加到chain的尾部
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });
//   利用while循環(huán),執(zhí)行完所有事件
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift()); 
} 
// 返回最終的promise對象
    return promise; 
}

核心axios對象到此已看完,下一節(jié)計劃分析dispatchRequest---adapter,真正發(fā)送請求的部分。喜歡就點個贊吧

參考文章:

AXIOS源代碼重點難點分析

es6-promise源代碼重點難點分析

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95851.html

相關(guān)文章

  • axios源碼閱讀

    摘要:響應(yīng)的攔截器接收到的是對象至此,我們已經(jīng)把的核心邏輯閱讀完畢,從中我們也可以看到的易用性和可拓展性非常強。尤其是可拓展性,發(fā)送請求到接收響應(yīng)的過程中的所有部分幾乎都是可拓展的,尤其是,,留下了很多想象的空間。 為了方便使用,axios對象既能做對象使用,又能做函數(shù)使用. axios.post(/user, { firstName: Fred, lastName: Fli...

    snifes 評論0 收藏0
  • 次eggjs+axios傳輸multipart的糾錯過程

    摘要:總所周知,的策略讓每次都要發(fā)送碼驗證,為了方便,我在的里作了前置攔截。結(jié)果不幸從此發(fā)生最開始沒有看官方文檔,以為應(yīng)該加在里面,又沒有考慮到要上傳格式的文檔,所以直接結(jié)果發(fā)送的是。這很正常,閱讀源碼知為時會自動添加的頭。不加又以上傳了。 總所周知,egg的csrf策略讓post每次都要發(fā)送token碼驗證,為了方便,我在axios的interceptor里作了前置攔截。 結(jié)果不幸從此發(fā)生...

    CarterLi 評論0 收藏0
  • Axios源碼深度剖析 - AJAX新王者

    摘要:我們先來看看構(gòu)造函數(shù)構(gòu)造函數(shù)就是用來實現(xiàn)攔截器的,這個構(gòu)造函數(shù)原型上有個方法。關(guān)于源碼,其實是比較簡單的,都是用來操作該構(gòu)造函數(shù)的實例屬性的。存放攔截器方法,數(shù)組內(nèi)每一項都是有兩個屬性的對象,兩個屬性分別對應(yīng)成功和失敗后執(zhí)行的函數(shù)。 Axios源碼分析 - XHR篇 文章源碼托管在github上,歡迎fork指正! axios 是一個基于 Promise 的http請求庫,可以用在瀏覽...

    DangoSky 評論0 收藏0
  • sau交流學(xué)習(xí)社區(qū)--看小說的lovebook個無線端BS應(yīng)用

    摘要:愛上閱讀,是一款的讀小說等書籍的并且閱讀的應(yīng)用。找了好久發(fā)現(xiàn)發(fā)現(xiàn)只有追書神器的暴露出來了,起點之類的找不到。八最后最后打個小廣告源碼都已在上開源,目前在逐步完善功能中。歡迎感興趣的同學(xué)和。 loveBook loveBook愛上閱讀,是一款webapp的讀小說等書籍的并且閱讀的應(yīng)用。如果覺得可以,歡迎fork和star。 自己最近在追斗破蒼穹電視劇,下班時候在地鐵上總聽到有人說,斗破蒼...

    leeon 評論0 收藏0
  • 微豆 - Vue 2.0 實現(xiàn)豆瓣 Web App 教程

    摘要:微豆一個使用與重構(gòu)豆瓣的項目。在中的配置代理重新啟動,打開查看結(jié)果是否與直接請求豆瓣相同。更多請參考豆瓣電影文檔。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。 微豆 Vdo 一個使用 Vue.js 與 Material Design 重構(gòu) 豆瓣 的項目。 項目網(wǎng)站 http://vdo.ralfz.com/ GitHub https:...

    cjie 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<