前端异步编程(2) AJAX

45 阅读3分钟

1. 什么是ajax?

Asynchronous JavaScript And XML(异步javascript和XML)

Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术,它很重要的特性之一就是让页面实现局部刷新。

特点:局部刷新页面,无需重载整个页面。 最终要实现的样子

ajax({
    type: "GET",
    url: "http://129.0.0.1"8080",
    data: {a: 1,b: 2},
    timeout: 3000,
    success: (res) => {
        console.log("成功",res)
    },
    error: (err) => {
        console.log("失败",err)
    }
})

2. XMLHttpRequest

XMLHttpRequest是实现ajax的一种方式是浏览器提供的一个构造函数

2.1 浏览器差异

先判断浏览器是否有XMLHttpRequest构造函数,ie5\6是ActiveXObject构造函数

let xmlhttp
if(window.XMLHttpRequest){
    xmlhttp = new XMLHttpRequest()
}else{
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP)
}

2.2 需要用到的属性和方法

实例化出来的xmlhttp有很多的属性和方法

截屏2023-07-30 21.33.28.png

常用的有onreadystatechangereadyStatestatusresponseTextresponseXML

  • readyState: 请求状态码,表示当前异步实例对象的状态,从0-4 默认为0
    • 0:表示请求未初始化,还没有调用open()
    • 1: 服务器连接已建立但是还没有调用send()
    • 2: 请求已接受,正在处理中,这个时候可以从响应中获取到内容头
    • 3: 请求处理中,响应中有部分数据可用,但是没有全部完成
    • 4: 请求已完成,数据全部解析完毕,可以获取到全部响应的数据
  • onreadystatechange:
    • 主要是用来监听readyState的状态变化,每当readyState状态变化时就会触发这个方法
  • status: http状态码(200-300[不包括],304)
  • responseText: 后台返回的字符串形式的响应数据
  • responseXML: 后台返回的XML形式的响应数据

2.3 请求方式和请求地址

使用open方法设置。有三个参数:请求方法、请求URL、是否异步 xmlHttp.open("POST","/api/user",true) ajax的意义就是发起异步请求,所以第三个参数一定是true

注意

IE浏览器有一个缓存问题:在IE浏览器中如果通过ajax发送的get请求,那么IE浏览器认为,同一个URL只有一个结果,所以如果请求地址没有变化,它就会直接返回上一次的请求结果。 所以通常的解决方法就是,每次get请求的URL拼接一个时间戳new Date().getTime() 用来保证每次请求的URL不一样

xmlHttp.open("get","/api/xxx"+(new Date().getTime()),true)

2.4 发送请求

通过send方法发送请求

xmlhttp.send()

如果是post请求要使用setRequestHeader()来添加HTTP请求头

xmlHttp.open("POST","ajax_test.html",true); 
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
xmlHttp.send("fname=Henry&lname=Ford");

2.5 监听readyState的状态变化

xmlhttp.onreadystatechange = () => {
    if(xmlhttp.readyState == 4){
        //请求完成
        if(xmlhttp.status >= 200 && xmlhttp.status < 300 | xmlHttp.status == 304){
            //c接收到服务器返回的数据
        }else{
            // 请求失败、响应错误
        }
    }
}

注意:如果请求的URL中有中文需要通过encodeURIComponent()转码

2.6.完整代码

const ajax = (option) => {
    
    let xmlhttp
    if(window.XMLHttpRequest){
        xmlhttp = new XMLHttpRequest()
    }else{
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP)
    }
    
    // 将传入的data(对象)转化为string
    let objToString = (obj) => {
        obj.t = new Date().getTime() // 这里主要是为get请求准备以处理IE浏览器的缓存问题
        let res = []
        for(let key in obj){
            res.push(`${encideURIComponent(key)}=encodeURIComponent(obj[key])`)
        }
        return res.join("&")
    }
    
    // 设置请求方式和请求URL
    let str = objToString(option.data)
    if(option.type.toLowerCase() === 'get'){
        xmlhttp.open('get', option.url+'?t='+option.data.t+str,true)
        xmlhttp.send()
    }else{
        xmlhttp.open(option.type, option.url, true)
        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
        xml.send(str)
    }
    
    // 监听状态变化
    xmlhttp.onreadystatechange = function() {
        clearInterval(timer)
        if(xmlhttp.readyState === 4){
            //请求完成
            if(xmlhttp.status >= 200 && xmlhttp.status < 300 | xmlHttp.status == 304){
                //c接收到服务器返回的数据
                option.success(xmlhttp.responseText)
            }else{
                // 请求失败、响应错误
                option.error(xmlhttp.responseText)
            }
        }
    }
    
    if(option.timeout){
        timer = setInterval(() => {
             xmlhttp.abort()//中断请求
             clearInterval(timer)
        },option.timeout)
    }    
}

2.7.总结

  1. 实例化 XMLHttpRequest,判断浏览器支持的构造函数是谁
  2. 判断请求方法,并连接。如果是get就直接将data数据拼接到url上,并且添加一个时间戳以处理IE浏览器的缓存问题。其他的方法就设置一个请求头send中发送数据
  3. 通过onreadystatechange 监听请求状态。
  4. 再根据http状态码判断请求是否成功
  5. 根据timeout的时间设置请求中断(要注意清除定时器)

3. fetch

fetch 是在 ES6 出现的。它是 XMLHttpRequest的替代品。

但是用的好好的,为什么要提代它呢?

待更新。。。