亲宝软件园·资讯

展开

ajax、fetch和axios的比较

谷歌玩家 人气:0

AJAX、Fetch、axios

AJAX

AJAX可以在不更新全局的情况下更新局部页面。通过在与服务器进行数据交换,可以使网页实现异步更新。

AJAX的原理就是通过XHR对象来向服务器发起异步请求,从服务器获得数据,然后用JS来操作DOM更新页面。领导想找小李汇报一下工作,就委托秘书去叫小李,自己就接着做其他事情,直到秘书告诉他小李已经到了,最后小李跟领导汇报工作。Ajax请求数据流程与“领导想找小李汇报一下工作”类似,上述秘书就相当于XMLHttpRequest对象,领导相当于浏览器,响应数据相当于小李。浏览器可以发送HTTP请求后,接着做其他事情,等收到XHR返回来的数据再进行操作。

image

创建AJAX

// 1. 创建 XMLHttpRequest 实例
let xhr = XMLHttpRequest()
// 2. 打开和服务器的连接
xhr.open('get', 'URL')
// 3.发送
xhr.send()
// 4. 接收变化。
xhr.onreadystatechange = () => {
    if(xhr.readyState == 4 && xhr.status == 200){   // readyState: ajax 状态,status:http 请求状态
        console.log(xhr.responseText);   //响应主体
    }
}
  1. http methods 请求方式:post,get,delete,put,head,options,trace,connect
  2. url:想服务器请求的路径
  3. async:是否为异步请求
  4. userName、userPass:用户名与密码

AJAX的缺点:

axios原理

axios是使用promise封装的ajax,它内部有两个拦截器,分别是request拦截器和response拦截器。

axios的特点

axios常用的方法

axios常用的方法有getpostputpatchdelete等。其中getpost返回的都是promise对象,可以使用promise方法

axios.get(url[, config]):get请求用于列表和信息查询

axios.get('apiURL', {
    param: {
        id: 1
    }
    // param 中的的键值对最终会 ? 的形式,拼接到请求的链接上,发送到服务器。
}).then(res => {
    console.log(res);
})
.catch( error => {
    console.log(error)
}

axios.delete(url[, config]):删除

axios.delete('apiURL', {
    params: {
        id: 1
    },
    timeout: 1000
})

axios.post(url[, data[, config]]):post请求用于信息的添加

axios.post('apiURL',{
        user: '小新',
        age: 18
}).then( res => {
    console.log(res);
})
.catch( error => {
    console.log(error)
}

axios.put(url[, data[, config]]):更新操作

axios.put('apiURL', {
    name: '小新',
})

axios.patch(url[, data[, config]]):更新操作

axios.patch('apiURL', {
    id: 13,
},{
   timeout: 1000,
})

put和patch的区别

patch方法用来更新局部资源,假设我们有一个UserInfo,里面有userId,userName,userGender等10个字段。可你的编辑功能因为需求,在某个特别的页面里只能修改userName,这个时候就可以使用patch

put也适用于更新数据,但必须提供完整的资源对象。

axios相关配置

axios拦截器执行顺序问题

例如:

axios.interceptors.request.use(config => {
  console.log(`请求拦截1`);
  return config;
});
axios.interceptors.request.use(config => {
  // 在发送请求之前做些什么 
  console.log(`请求拦截2`);
  return config;
});

// 添加响应拦截器 
axios.interceptors.response.use(response => {
  // 对响应数据做点什么 
  console.log(`成功的响应拦截1`);
  return response.data;
});

// 添加响应拦截器 
axios.interceptors.response.use(response => {
  // 对响应数据做点什么 
  console.log(`成功的响应拦截2`);
  return response;
});

// 发送请求 
axios.get('/posts')
  .then(response => {
    console.log('成功了');
  }) 

执行结果为

console.log("请求拦截2");
console.log("请求拦截1");
console.log("成功的响应拦截1");
console.log("成功的响应拦截2");
console.log("成功了");

为什么axios中需要拦截器

在SPA应用中,通常会使用token进行用户身份认证,这就要求每次请求必须携带用户的身份信息,针对这个需求,为了避免在每个请求中单独处理,我们可以通过封装统一的request函数来为每隔请求统一添加token信息。

但如果想为某些请求添加缓存时间或者控制某些请求的调用频率的话,我们就需要不断地修改request函数来扩展对应的功能。此时,如果在考虑对响应进行统一处理,我们的request函数将变得越来越庞大,也越来越难维护。所以axios为我们提供了拦截器。

为什么请求拦截2会在请求拦截1之前执行呢?

axios源码中将发送请求分为了请求拦截器、发送请求、响应拦截器、相应回调,通过Promise的链式调用将这些部分结合起来了,这样就得到了发送请求拿到数据的全部过程。

下面分析源码:

image

fetch
fetch是http请求数据的方式,它使用Promise,但不使用回调函数。fetch采用模块化设计,通过数据流处理数据,对于请求大文件或网速慢的情况相当有用。默认情况下fetch不会接收或发送cookies。

优点:

缺点:

Fetch、ajax与axios的区别

Fetch和Ajax比有什么优点

Fetch使用的是promise,方便使用异步,没有回调地狱的问题。

总结

image

Ajax是一种web数据交互的方式,它可以使页面在不重新加载的情况下请求数据并进行局部更新,它内部使用了XHR来进行异步请求。Ajax在使用XHR发起异步请求时得到的是XML格式的数据,如果想要JSON格式,需要进行额外的转换;Ajax本身针对的是MVC框架,不符合现在的MVVM架构Ajax有回调地狱问题;Ajax的配置复杂

Fetch是XHR的代替品,它基于Promise实现的,并且不使用回调函数,它采用模块化结构设计,并使用数据流进行传输,对于大文件和网速慢的情况非常友好。但是Fetch不会对请求和响应进行监听;不能阻断请求;过于底层,对一些状态码没有封装;兼容性差。

axios是基于PromiseXHR进行封装,它内部封装了两个拦截器,分别是请求拦截器和响应拦截器。请求拦截器用于在请求发出之前进行一些操作,比如:设置请求体,携带Cookie、token等;响应拦截器用于在得到响应后进行一些操作,比如:登录失效后跳转到登录页面重新登录。axios有get、post、put、patch、delete等方法。axios可以对请求和响应进行监听;返回Promise对象,可以使用Promise的API;返回JSON格式的数据;由浏览器发起请求;安全性更高,可以抵御CSRF攻击。

axios源码分析

axios的执行流程

image

入口文件(lib/axios.js)

导出的axios就是 实例化后的对象,还在其上挂载create方法,以供创建独立的实例,实现实例之间互不影响。

// 创建实例过程的方法
function createInstance(defaultConfig) {
  return instance;
}
// 实例化
var axios = createInstance(defaults);
 
// 创建独立的实例,隔离作用域
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
// 导出实例
module.exports = axios;

createInstance()

function createInstance(defaultConfig) {
  // 实例化,创建一个上下文
  var context = new Axios(defaultConfig);
 
  // 平时调用的 get/post 等等请求,底层都是调用 request 方法
  // 将 request 方法的 this 指向 context(上下文),形成新的实例
  var instance = bind(Axios.prototype.request, context);
 
  // Axios.prototype 上的方法 (get/post...)挂载到新的实例 instance 上,
  // 并且将原型方法中 this 指向 context
  utils.extend(instance, Axios.prototype, context);
 
  // Axios 属性值挂载到新的实例 instance 上
  // 开发中才能使用 axios.default/interceptors
  utils.extend(instance, context);
 
  return instance;
}

createInstance执行流程:

可以看到axios不是简单的创建实例context,而是在context上进行this绑定形成新的实例,然后将Axios属性和请求方法挂载到新的实例上

拦截器(lib/core/InterceptorManager.js)

拦截器涉及一个属性和三个方法:

function InterceptorManager() {
  // 存放 use 注册的回调函数
  this.handlers = [];
}

InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
  // 注册成功和失败的回调函数
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected,
    ...
  });
  return this.handlers.length - 1;
};

InterceptorManager.prototype.eject = function eject(id) {
  // 删除注册过的函数
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
};

InterceptorManager.prototype.forEach = function forEach(fn) {
  // 遍历回调函数,一般内部使用多
  utils.forEach(this.handlers, function forEachHandler(h) {
    if (h !== null) {
      fn(h);
    }
  });
};

dispatchRequest(lib/core/dispatchRequest.js)

dispatchRequest主要做了以下操作:

image

取消请求(lib/cancel/CancelToken.js)

var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

总结

加载全部内容

相关教程
猜你喜欢
用户评论