文章目录

  • ajax、axios相关的面试题
  • 面试题
  • 概述
  • axios拦截器原理
  • axios取消请求的原理
  • 手写ajax (简单的axios)
  • XHR对象的常用方法或属性


ajax、axios相关的面试题

面试题

  • axios的优点,axios和ajax的区别
  • 原生实现ajax,说一下怎么用ajax发送请求
  • ajax的封装,取消请求,使用ajax封装类似axios可以实现的拦截器功能
  • axios 的拦截器原理
  • 那axios是怎样取消请求的

概述

axios是什么?
基于promise的异步ajax请求库

axios有什么新特点?

  • 支持请求/响应拦截器 ★
  • 支持请求取消
  • .浏览器端(创建ajax请求)/node端(创建一般的HTTP请求)都可以使用
  • 请求/响应数据转换 --> 使用时写的是对象,axios自动转换成了json。接受时axios也自动将json转换为了对象

axios拦截器原理

拦截器的使用

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
  	  // 对请求错误做些什么
    return Promise.reject(error);
  });
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});

const interceptorId = axios.interceptors.request.use(function () {/*...*/}); 
axios.interceptors.request.eject(interceptorId); 
/*
在axios对象属性中暴露出了一个interceptors这个属性对象,该对象有两个属性分别是request、response,这两个属性存分别对应请求前与请求后我们想做的一些操作,再调用use函数配置了两个函数进去。
*/

拦截器原理: 本质是一个顺序问题 请求拦截器-api请求-响应拦截器

  1. 拦截器中,定义了handlers 数组收集了所有的拦截器方法。
  2. axios使用的是数组的方式完成了链式调用,通过request与response的forEach方法,将请求拦截器插入到chain(请求api)的前面,将响应拦截器插入到chain(请求api)的后面。
  3. 执行时从队头开始执行,所以请求拦截器后设置的先执行,响应拦截器先设置的先执行。
var promise = Promise.resolve(config);
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

axios取消请求的原理

取消请求的使用
1.excutor执行器函数是同步执行的,参数是用于取消当前请求的函数
2.当取消当前请求的函数被调用时,该请求会进入失败的流程,请求失败的error是Cancel对象类型,Cancel里面有message属性

let cancel //保存用于取消请求的函数
axios.get("/user",{
	//new axios.CancelToken时得到一个函数
     cancelToken:new axios.CancelToken(function excutor(c){
	 	cancel = c; //准备发请求时先把取消请求的函数保存起来,后续可以调用来取消当前请求
	}).then(response =>{
        cancel = null; //如果请求完成就不要取消请求了
    },error =>{
		cancel = null; //失败之后也不需要取消了
	})
})

取消请求的原理

  1. new axios.CancelToken时函数内部准备一个promise对象,并将promise的resolve函数保存起来。
  2. 执行外部定义的执行器函数,将取消函数作为参数传递。取消请求函数的作用是执行时将promise指定为成功,值为Cancel对象。
    3.当取消请求函数执行时(将promise修改成成功了),获取之前保存的promise状态,如果成功并且请求还没有执行完成则执行request.abort()中断请求,并调用reject(cancel对象)将发请求的promise状态改为失败。
function CancelToken(excutor){
//...
let resolvePromise;
//为取消请求准备一个promise对象,并保存resolve函数
this.promise = new Promise(function promiseExecutor(resolve){
	resolvePromise = resolve;
})
let token = this; //保存当前CancelToken对象
//执行同步执行器,function cancel为参数,这个参数就取消请求的参数
excutor(function cancel(message){ 
	//....
	//将token的reason指定为一个Cancel对象
	token.reason = new Cancel(message);
	resolvePromise(token.reason); //将取消请求的promise指定为成功,成功的值为reason
})
}

//取消请求部分的代码
if(config.cancelToken){
	config.cancelToken.promise.then(function onCanceled(cancel){
		if(!request)return;
		request.abort();//中断请求
		reject(cancel);
		request = null
	})
}

手写ajax (简单的axios)

  1. 参数是option配置对象,返回promise对象
  2. 利用XHR对象发送ajax请求
  1. 创建xhr对象new XMLHttpRequest()
  2. 初始化xhr连接xhr.open(method,url,true) 默认async:true,参数是请求行
  3. 发送请求xmr.send() 参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串
  4. xml.onreadystatechange 用于监听请求状态的改变,send是异步的
    readyState 0:初始 1:open()之后 2:send()之后 3:请求中 4:请求完成
  1. 处理结果,返回status、statusText 以及响应数据,数据需要转换为字符串/对象格式
function axios({
	url,
	method='GET',
	params={},
	data={},
}){
	return new Promise(resolve,reject){
    //数据初始化操作
    let query ='' ;
    Object.keys(params).forEach(key => {
        query += `${key}=${params[key]}&` 
    })
    if(query){
      query = query.substring(0,query.length-1);
      url = url + '?' + query;
    }
    method = method.toUpperCase();
    let xhr = new XMLHttpRequest() //创建xhr对象
    xhr.open(url,method); //初始化请求

    //状态监听,send是异步的
    xhr.onreadystatechange = function(){
      if(xhr.readyState !==4) return;
      //请求完成
      let {status,statusText} = xhr;
      if (status>=200&&status<=299){
        const response = {
          data:JSON.parse(xhr.response),
          status,
          statusText,
      }
      resolve(response)
      }else{
        reject(new Error(`request error status is ${status}`))
      }
    }

    switch(method){//发送请求
        case 'GET' || 'DELETE':
          xhr.send();
          break;
        case 'POST' || 'PUT':
          xhr.setRequestHeader("Content-Type","application/json;charset=utf");
          xhr.send(JSON.stringify(data));
    } 
	}
}

XHR对象的常用方法或属性

方法/属性

描述

readyState

请求的状态 0:初始 1:open()之后 2:send()之后 3:请求中 4:请求完成

onreadystatechange监视回调函数

绑定readyState改变的监听 on…当…时执行

open(method,url[,async])

初始化一个请求 默认async:true,参数是请求行

send(data)

发送请求 参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串

abort()

中断请求 中断的是发出请求,还没结束的请求