爲了方便使用,axios對象既能作對象使用,又能作函數使用.node
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } });
這一點axios是如何作到的,能夠看到instance實際上是一個綁定this的函數,調用axios就是調用context.requestios
function createInstance(){ // 能當作函數使用的祕密 var instance = bind(Axios.prototype.request, context); // 能當作對象使用的祕密 utils.extend(instance, Axios.prototype, context); // 要拿到構造函數繼承的屬性 utils.extend(instance, context); return instance } var axios = createInstance(defaults);
接下來咱們看一下request方法,全部http請求的發送都會調用Axios.prototype.request
,這個函數能夠認爲是整個axios的骨架,很是重要。axios
Axios.prototype.request = function request(config) { // 每一個請求都會從新合成一個config,因此經過操做config對象,你能夠標識請求,作某些操做,事實上每一個axios的攔截器都能拿到config對象 config = utils.merge(defaults, this.defaults, { method: 'get' }, config); // 掛載攔截器的主要邏輯 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; }
從攔截器中的主要邏輯,咱們能夠獲得如下幾點:promise
interceptors.request.use(function () {/*...*/})
執行的順序有關,即先use
的請求攔截器會先執行。看一下,不一樣的http method是怎麼複用request方法的緩存
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 })); }; });
接下來咱們看dispatchRequest的核心邏輯:異步
// 處理config... 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); });
能夠看到dispatchRequest的核心邏輯大概有三步async
因此經過dispatchRequest方法的閱讀,咱們能夠獲得如下啓示:函數
至此,咱們已經把axios的核心邏輯閱讀完畢,從中咱們也能夠看到axios的易用性和可拓展性很是強。post
尤爲是可拓展性,發送請求到接收響應的過程當中的全部部分幾乎都是可拓展的,尤爲是config,adapter,interceptor留下了不少想象的空間。this