封装Ajax请求

325 阅读3分钟

引言:

我们知道原生Ajax请求是基于XMLHttpRequest的,在本文中首先介绍下XMLHttpRequest的相关基本知识,然后基于Promise封装一个Ajax请求。

XMLHttpRequest简介

这部分的内容主要参考MDN上对于XMLHttpRequest的介绍

XMLHttpRequest

XMLHttpRequest是什么?

简单一句话,浏览器是通过XMLHttpRequest与服务器进行通信的,包括现在常用的axios库,都是基于XMLHttpRequest的。

一些常用的方法和属性

open方法

  • 初始化一个请求
  • 用法:xhr.open(method, url, flag)
    • method: Http方法:包括 get、post、header、put、delete等
    • url: 要请求的服务地址
    • flag: 可选,是否进行异步操作 默认true(异步)

setRequestHeader方法

  • 设置http请求头的方法
  • 用法: xhr.setRequestHeader(header, value)
    • header: 属性名
    • value:属性值

send方法

  • 发送http请求
  • 用法: xhr.send(params) params:发送的数据

readyState属性

  • 表示XMLHttpRequest实例当前所处的状态
  • 解释
描述
0 代理被创建,但尚未open
1 open()方法已经被调用
2 send()方法被调用
3 下载中
4 下载操作完成

state属性

  • XMLHttpRequest响应的数字状态码,也就是http状态码

onreadstatechange 属性

  • 返回一个回调函数
  • 表示readState变化,callback

封装Ajax

Ajax请求五步走

发送一个ajax请求,总共需要以下五个步骤:

  • 创建XMLHttpRequest对象
  • 创建http请求,与服务器连接
  • 设置请求头
  • 发送请求
  • 响应http状态变化的函数

来段代码,对上面的步骤进行一个说明

// 1.实例化XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 2.创建http请求 xhr.open(method, url, flag true同步)
xhr.open('get', 'http://localhost:2000/name', true);
// 3.设置请求头
xhr.setRequestHeader('Contend-Type', "application/json;charset=UTF-8");
// 4.发送请求
xhr.send(null);
// 处理post请求的参数封装
// var param = {
//     name : 'shaoyan',
//     age: 20
// }
// xhr.send(JSON.stringify(param))
// 5. 响应状态变化
xhr.onreadystatechange = function(){
    if(xhr.readyState ==4 && xhr.status === 200){
        console.log(JSON.parse(xhr.response) )
    }
}

基于Promise封装Ajax请求

基于上面的五步走,采用Promise,来封装一个方法,我会在代码中加注释做说明。

/**
 * 封装一个链式ajax请求
 * @param obj 传入的参数
 */
 function ajaxHttp(obj){
 //默认参数, 如果没传的话用这个
     let oriObj = {
        method: 'get',
        url: '/',
        async: true,
        data: null,
        contentType: `application/json;charset=UTF-8`
     }
     
     // 将传入的参数与默认参数合并
     let endObj = Object.assign({}, oriObj, obj)
     
     // 封装成链式结构
     return new Promise((resolve, reject)=> {
         let {method, url, data, async, contentType} = endObj
         // 1.实例化XMLHttpRequest
         let xhr = new XMLHttpRequest()
         // get方法的话对参数进行拼接成 ? name= '' & age = 这种形式
         let isGet = method === 'get'? true: false
         if(isGet && data){
            let params = ''
            for(let key in data){
                params += `${key} = ${endObj.data[key]} &`
            }
            url += '?' + params.substring(0, params.length-1) 
         }
        // 2. 创建http请求
        xhr.send(method, url, async)
        // 3. 设置请求头
        xhr.setRequestHeader('content-type', contentType)
        // 4. 发送数据
        if(!data){
            xhr.send(null)
        }else{
            JSON.stringify(data)
        }
        // 5. 响应http状态变化
        xhr.onreadystatechange = ()=>{
            if(xhr.readyState === 4){
                if(xhr.status === 200){
                    resolve(xhr.response)
                }else{
                    reject('错误')
                }
            }else{
                reject('错误')
            }
        }
     })
 }

这样, 我们就封装了一个简单的ajax请求,使用的时候可以采用链式调用,如下例子,是不是和axios的基本使用方法很像:

 ajaxHttp({
   method: 'get',
   url: `http://localhost:2000/name`,
   data: null
}).then((data)=>{
   console.log(data)
}).catch((res)=>{
   console.log(res)
})