axios 模拟实现
包含[发送请求,拦截器,取消请求]
第一步 , axios模拟发送请求
function xhr_adpter(config){return new Promise(function handle(resolve,reject){let xhr = new XMLHttpRequest();xhr.open(config.method, config.url,true);xhr.onreadystatechange = function(){if(4 === xhr.readyState){if(xhr.status >= 200 && xhr.status < 300){resolve({config,data:xhr.response,status:xhr.status,headers:xhr.getAllResponseHeaders(),request:xhr});return;}elsereject({data:xhr.response,status : xhr.status});}}xhr.send();});}function dispatch_req(config){return xhr_adpter(config).then(res=>{return res;},error=>{throw error;})} function Axios(config){this.config = config;}Axios.prototype.request = function(config){let promise = Promise.resolve(config);let callbacks = [dispatch_req, null] ;return promise.then(callbacks[0],callbacks[1]);}let context = new Axios({});let axios = Axios.prototype.request.bind(context);let new_promise = axios({method:"GET",url:"http://127.0.0.1/get_axios"});new_promise.then(res=>{console.log("get :", res); },error=>{console.log("error:",error)});
第二步,拦截器模拟
添加拦截器函数
function Interceptor(){this.handlers = [];}Interceptor.prototype.use = function(success=null, fail=null){this.handlers.push({success,fail});}
构造函数新增拦截器
function Axios(config){this.config = config;this.interceptors = {request: new Interceptor(),response : new Interceptor()};}
新增初始化函数
function prepare(){let context = new Axios({});let axios = Axios.prototype.request.bind(context);Object.keys(context).forEach(key=>{axios[key] = context[key];});return axios;}
修改请求函数
Axios.prototype.request = function(config){let promise = Promise.resolve(config);let callbacks = [dispatch_req, null] ;while(this.interceptors.request.handlers.length > 0){let handler = this.interceptors.request.handlers.shift();callbacks.unshift(handler.success, handler.fail);}while(this.interceptors.response.handlers.length > 0){let handler = this.interceptors.response.handlers.shift();callbacks.push(handler.success, handler.fail)}while(callbacks.length > 0){let success = callbacks.shift();let fail = callbacks.shift();promise = promise.then(success,fail);}return promise;}
拦截器完整代码
function Interceptor(){this.handlers = [];}Interceptor.prototype.use = function(success=null, fail=null){this.handlers.push({success,fail});}function xhr_adpter(config){return new Promise(function handle(resolve,reject){let xhr = new XMLHttpRequest();xhr.open(config.method, config.url,true);xhr.onreadystatechange = function(){if(4 === xhr.readyState){if(xhr.status >= 200 && xhr.status < 300){resolve({config,data:xhr.response,status:xhr.status,headers:xhr.getAllResponseHeaders(),request:xhr});return;}elsereject({data:xhr.response,status : xhr.status});}}xhr.send();});}function dispatch_req(config){return xhr_adpter(config).then(res=>{return res;},error=>{throw error;})} function Axios(config){this.config = config;this.interceptors = {request: new Interceptor(),response : new Interceptor()};}Axios.prototype.request = function(config){let promise = Promise.resolve(config);let callbacks = [dispatch_req, null] ;while(this.interceptors.request.handlers.length > 0){let handler = this.interceptors.request.handlers.shift();callbacks.unshift(handler.success, handler.fail);}while(this.interceptors.response.handlers.length > 0){let handler = this.interceptors.response.handlers.shift();callbacks.push(handler.success, handler.fail)}while(callbacks.length > 0){let success = callbacks.shift();let fail = callbacks.shift();promise = promise.then(success,fail);}return promise;}function prepare(){let context = new Axios({});let axios = Axios.prototype.request.bind(context);Object.keys(context).forEach(key=>{axios[key] = context[key];});return axios;}axios = prepare();axios.interceptors.request.use(config=>{console.log("请求1",config)return config;},error=>{});axios.interceptors.request.use(config=>{console.log("请求2",config)return config;},error=>{});axios.interceptors.response.use(res=>{console.log("响应1");return res;});axios.interceptors.response.use(res=>{console.log("响应2");return res;});let new_promise = axios({method:"GET",url:"http://127.0.0.1/get_axios"});new_promise.then(res=>{console.log("get :", res); },error=>{console.log("error:",error)});
添加取消请求
代码较为简单,只贴出新增代码
function AbortSignal(){let resolve_func;this.promise = new Promise(resolve=>{resolve_func = resolve;});this.abort = resolve_func;}
在xhr发送请求的代码中添加 取消请求的处理
function xhr_adpter(config){return new Promise(function handle(resolve,reject){let xhr = new XMLHttpRequest();xhr.open(config.method, config.url,true);if(config.signal){config.signal.promise.then(res=>{xhr.abort();});}});}
let abort_signal = new AbortSignal();let new_promise = axios({method:"GET",url:"http://127.0.0.1/get_axios",signal: abort_signal });new_promise.then(res=>{console.log("get :", res); },error=>{console.log("error:",error)});setTimeout(() => {abort_signal.abort();}, 1000);