欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)激活碼778899分享:前端 axios原理

柚子快報(bào)激活碼778899分享:前端 axios原理

http://yzkb.51969.com/

文章目錄

axios基本概念axios多種方式調(diào)用工具函數(shù)axios的攔截器如何實(shí)現(xiàn)?用的設(shè)計(jì)模式是哪種?axios如何實(shí)現(xiàn)取消請求,和cancelToken如何使用手寫一個(gè)簡單axios

axios基本概念

axios是目前比較流行的一個(gè)js庫,是一個(gè)基于promise的網(wǎng)絡(luò)數(shù)據(jù)請求庫,主要用于發(fā)送網(wǎng)絡(luò)數(shù)據(jù)請求,從后臺(tái)服務(wù)器上獲取數(shù)據(jù)返回給前端。

優(yōu)點(diǎn)特性:

從瀏覽器中創(chuàng)建 XMLHttpRequests從 node.js 創(chuàng)建 http 請求支持 Promise API攔截請求和響應(yīng)轉(zhuǎn)換請求數(shù)據(jù)和響應(yīng)數(shù)據(jù)取消請求自動(dòng)轉(zhuǎn)換 JSON 數(shù)據(jù)客戶端支持防御 XSRF

axios多種方式調(diào)用

axios的常用幾種方式就是:

axios.get(url,config); url表示請求地址,config表示配置對(duì)象axios.post(url,config)axios(config)

從上面可以看出axios既可以當(dāng)函數(shù)axios()使用又可以當(dāng)對(duì)象axios.get()使用,原理: 實(shí)質(zhì)上axios是一個(gè)函數(shù),但函數(shù)也屬于是一個(gè)對(duì)象,所以同樣可以向它身上追加屬性和方法,我們所使用的axios是通過createInstance這個(gè)函數(shù)創(chuàng)造出來的,它簡單實(shí)現(xiàn)的源碼如下。 函數(shù)中實(shí)例化了Axios,Axios真正調(diào)用的是Axios原型鏈上的request方法;因此導(dǎo)出的axios需要關(guān)聯(lián)到request方法,這里巧妙的通過bind函數(shù)進(jìn)行關(guān)聯(lián),生成關(guān)聯(lián)后的instance函數(shù),同時(shí)指定它的調(diào)用上下文就是Axios的實(shí)例對(duì)象,因此instance調(diào)用時(shí)也能獲取到實(shí)例對(duì)象上的defaults和interceptors屬性;但是僅僅關(guān)聯(lián)request還不夠,再通過extend函數(shù)將Axios原型對(duì)象上的所有g(shù)et、post等函數(shù)擴(kuò)展到instance函數(shù)上,因此這也是我們才能夠使用多種方式調(diào)用的原因所在。

function createInstance(defaultConfig) {

// 1.實(shí)例化Axios

var context = new Axios(defaultConfig);

// 2.注意這里bind是一個(gè)自定義函數(shù),返回一個(gè)函數(shù)()=>{Axios.prototype.request.apply(context,args)}

// 這里request基本是Axios的核心方法,相當(dāng)于將這些方法全部綁到了實(shí)例化的對(duì)象上

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

// Copy axios.prototype to instance

// 3.將Axios原型鏈上的其他方法也都綁定到instance上去,這些方法的this會(huì)指向contxt

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

// Copy context to instance

// 4.將contxt上的屬性復(fù)制到instance上去

utils.extend(instance, context);

return instance;

}

axios的構(gòu)造函數(shù)Axios,Axios函數(shù)在原型對(duì)象上還掛載了request、get、post等函數(shù),但是get、post等函數(shù)最終都是通過request函數(shù)來發(fā)起請求的。而且request函數(shù)最終返回了一個(gè)Promise對(duì)象, 因此我們才能通過then函數(shù)接收到請求結(jié)果。

class Axios {

constructor(instanceConfig) {

this.defaults = instanceConfig;

this.interceptors = {

request: new InterceptorManager(),

response: new InterceptorManager()

};

}

request() {}

}

一個(gè)是將默認(rèn)配置保存到defaults,另一個(gè)則是構(gòu)造了interceptors攔截器對(duì)象 核心request函數(shù)主要作用:

兼容多種傳參方式(1. request(‘example/url’, { method: ‘post’ }); request({ url: ‘example/url’, method: ‘post’ }))合并參數(shù)通過promise的鏈?zhǔn)秸{(diào)用,處理請求、響應(yīng)攔截器以及發(fā)送請求等操作。

工具函數(shù)

bind:將Axios原型上的方法掛載到instance上extend:將構(gòu)造函數(shù) Axios.prototype 上的方法掛載到新的實(shí)例 instance 上,然后將原型各個(gè)方法中的 this 指向 context

axios的攔截器如何實(shí)現(xiàn)?用的設(shè)計(jì)模式是哪種?

攔截器實(shí)現(xiàn)就只有一個(gè)屬性(用于保存攔截器)及三個(gè)原型方法(添加、移除、執(zhí)行)。

實(shí)例化axios后,就可以調(diào)用use進(jìn)行綁定攔截器,需要注意的是,在傳遞use方法的第一個(gè)參數(shù)時(shí)必須返回config,保證下一個(gè)promise能獲取到處理后的參數(shù)。 options是可選參數(shù)對(duì)象,可傳入兩個(gè)屬性(synchronous, runWhen),這么設(shè)計(jì)就是使用了責(zé)任鏈設(shè)計(jì)模式。

axios采用promise.resolve的方式將攔截器異步化。將所有請求攔截器放在請求方法之前unshift,所有的響應(yīng)攔截器放在后push。遍歷所有的方法通過promise的then方法將所有方法放在一條鏈上。

責(zé)任鏈模式是一種行為設(shè)計(jì)模式, 允許你將請求沿著處理者鏈進(jìn)行發(fā)送。 收到請求后, 每個(gè)處理者均可對(duì)請求進(jìn)行處理, 或?qū)⑵鋫鬟f給鏈上的下個(gè)處理者。 優(yōu)點(diǎn):

你可以控制請求處理的順序。單一職責(zé)原則。 你可對(duì)發(fā)起操作和執(zhí)行操作的類進(jìn)行解耦。開閉原則。 你可以在不更改現(xiàn)有代碼的情況下在程序中新增處理者。

責(zé)任鏈模式:執(zhí)行的順序是請求攔截器 -> 發(fā)起請求 -> 響應(yīng)攔截器,這其實(shí)就是一個(gè)鏈條上串起了三個(gè)職責(zé)。

axios如何實(shí)現(xiàn)取消請求,和cancelToken如何使用

創(chuàng)建一個(gè) CancelToken 的實(shí)例,它有一個(gè) executor 函數(shù),可以通過調(diào)用 executor 參數(shù)中的 cancel 函數(shù)來取消請求。(CancelToken內(nèi)部通過promise實(shí)現(xiàn),將promise的resolve方法暴露出去,手動(dòng)控制promise狀態(tài))在 axios 請求配置中指定 cancelToken 屬性,將 CancelToken 實(shí)例傳遞進(jìn)去。(axios 內(nèi)部注冊回調(diào)取消函數(shù),真正的取消方法,XMLHttpRequest 的abort方法取消請求)當(dāng)我們需要取消請求時(shí),調(diào)用 CancelToken 實(shí)例的 cancel() 方法即可取消對(duì)應(yīng)的請求。(內(nèi)部executor傳出來的函數(shù),函數(shù)中包含了resolvePromise(),手動(dòng)改變promise狀態(tài),執(zhí)行then(),執(zhí)行所有被注冊的函數(shù),也就是執(zhí)行真正的abort())

使用方法:

import axios from 'axios';

const CancelToken = axios.CancelToken;

let cancel;

// 【方法1】

axios.get('/user/12345', {

cancelToken: new CancelToken(function executor(c) {

// executor 函數(shù)接收一個(gè) cancel 函數(shù)作為參數(shù)

cancel = c;

})

});

cancel('Operation canceled by the user.');

// 【方法2】

const CancelToken = axios.CancelToken;

const source = CancelToken.source();

axios.post('/user/12345', {

name: 'new name'

}, {

cancelToken: source.token

})

source.cancel('Operation canceled by the user.');

源碼: axios/lib/adapters/xhr.js

// 當(dāng)我們使用時(shí),傳入cancelToken配置

if (config.cancelToken || config.signal) {

onCanceled = cancel => {

if (!request) {

return;

}

reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel);

request.abort();

request = null;

};

// 注冊回調(diào)取消函數(shù)

config.cancelToken && config.cancelToken.subscribe(onCanceled);

if (config.signal) {

config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);

}

}

lib/cancel/CancelToken.js

class CancelToken {

constructor(executor) {

if (typeof executor !== 'function') {

throw new TypeError('executor must be a function.');

}

// 將promise中的resolve()暴露出去

let resolvePromise;

this.promise = new Promise(function promiseExecutor(resolve) {

resolvePromise = resolve;

});

// 將 CancelToken 實(shí)例賦值給 token

const token = this;

// peomise狀態(tài)改變后,執(zhí)行oncanceled()

this.promise.then(cancel => {

if (!token._listeners) return;

let i = token._listeners.length;

while (i-- > 0) {

token._listeners[i](cancel);

}

token._listeners = null;

});

// ??沒看懂

this.promise.then = onfulfilled => {

let _resolve;

const promise = new Promise(resolve => {

token.subscribe(resolve);

_resolve = resolve;

}).then(onfulfilled);

promise.cancel = function reject() {

token.unsubscribe(_resolve);

};

return promise;

};

// 執(zhí)行executor,這里定義的cancel函數(shù)即時(shí)業(yè)務(wù)中調(diào)用的cancel函數(shù)

executor(function cancel(message, config, request) {

if (token.reason) {

return;

}

token.reason = new CanceledError(message, config, request);

resolvePromise(token.reason); // 把接收到的“取消請求信息”token.reason傳遞給下一個(gè)then中成功函數(shù)作為參數(shù)

});

}

subscribe(listener) {

if (this.reason) {

listener(this.reason);

return;

}

if (this._listeners) {

this._listeners.push(listener);

} else {

this._listeners = [listener];

}

}

unsubscribe(listener) {

if (!this._listeners) {

return;

}

const index = this._listeners.indexOf(listener);

if (index !== -1) {

this._listeners.splice(index, 1);

}

}

// cancelToken.source工廠函數(shù),組合成source返回

static source() {

let cancel;

const token = new CancelToken(function executor(c) {

cancel = c; // 實(shí)現(xiàn)“在他處取消請求”,與上面“終止一個(gè)promise”異曲同工

});

return {

token,

cancel

};

}

}

手寫一個(gè)簡單axios

export function axios({ method, url, params, data }) {

method = method.toUpperCase();

return new Promise((resolve, reject) => {

// 1.創(chuàng)建對(duì)象

const xhr = new XMLHttpRequest();

// 2.初始化

let str = "";

for (const k in params) {

str += `${k}=${params[k]}&`;

}

str = str.slice(0, -1);

xhr.open(method, url + "?" + str);

// 3.發(fā)送請求

if (method === "POST" || method === "PUT" || method === "DELETE") {

// Content-type mime類型設(shè)置

// 請求頭

xhr.setRequestHeader("Content-type", "application/json");

// 請求體

xhr.send(JSON.stringify(data));

} else {

// 如果是get方法

xhr.send();

}

// 設(shè)置響應(yīng)結(jié)果的類型為json

xhr.responseType = "json";

// 4.處理結(jié)果

xhr.onreadystatechange = function () {

//

if (xhr.readyState === 4) {

// 判斷響應(yīng)狀態(tài)碼

if (xhr.status >= 200 && xhr.status <= 300) {

// 成功的狀態(tài)

resolve({

// 成功的狀態(tài)碼

status: xhr.status,

// 成功的字符串,響應(yīng)字符串

message: xhr.statusText,

// 響應(yīng)體

body: xhr.response,

});

} else {

reject(new Error("請求失敗,失敗的狀態(tài)碼為" + xhr.status));

}

}

};

});

}

axios.get = function (url, options) {

// 發(fā)送AJAX請求 GET

return axios(Object.assign(options, { method: "GET", url }));

};

axios.post = function (url, options) {

// 發(fā)送AJAX請求 POST

return axios(Object.assign(options, { method: "POST", url }));

};

axios.put = function (url, options) {

// 發(fā)送AJAX請求 PUT

return axios(Object.assign(options, { method: "PUT", url }));

};

axios.delete = function (url, options) {

// 發(fā)送AJAX請求 DELETE

return axios(Object.assign(options, { method: "DELETE", url }));

};

柚子快報(bào)激活碼778899分享:前端 axios原理

http://yzkb.51969.com/

精彩內(nèi)容

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19427423.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄