JavaScript手写简版ajax

1、介绍

        ajax:Asynchronous JavaScript And XML,翻译过来就是“异步的 Javascript 和 XML”。MDN中对ajax介绍:

        异步 JavaScript 和 XML 或 Ajax 本身不是一种技术,而是一种将一些现有技术结合起来使用的方法,包括:HTML 或 XHTML、CSS、JavaScript、DOM、XML、XSLT、以及最重要的 XMLHttpRequest 对象。

        所以 Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术。它的特点是:局部刷新页面,无需重载整个页面。

2、手写ajax

        利用 XMLHttpRequest 模块实现 Ajax。总共可以分为五步:

2.1、创建 XMLHttpRequest 对象
let xmlHttp;
if(window.XMLHttpRequest){
    // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlHttp = new XMLHttpRequest()
}else{
    // code for IE6, IE5
    xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
2.2、构建请求

        通过open()方法设置请求方式(GET/POST)和请求地址(url)

/**
 * 第一个参数:请求的类型;GET 还是 POST;
 * 第二个参数:表示请求的文件的地址url;
 * 第三个参数:设置请求方法是不是异步async,true为异步, false为同步。默认为true
 */
xmlHttp.open('GET/POST', url, true)
2.3、发送请求
// 可使用 setRequestHeader() 来设置HTTP请求头
// xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 

// send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
xmlHttp.send(body)
 2.4、监听状态变化

        XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。

        readyState:请求状态码,表示异步对象目前的状态,readyState的值从0到4。

状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用(即服务器连接已建立)。
2 HEADERS_RECEIVED

send() 方法已经被调用(即请求已接收,正在处理中),

并且头部和状态已经可获得。

3 LOADING

请求处理中,但没有全部完成;responseText 属性已经包含部分数据。

4 DONE 请求已完成。
2.5、处理请求返回结果

        status:http状态码;http状态码表示成功的http状态码有:

// 304状态码(Not Modified):表示客户端发送的请求资源未被修改,服务器端无需返回资源内容,而是直接使用缓存的内容。优化网络带宽的使用,减少了不必要的数据传输,提高网络的访问速度。
xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304

        responseText:后台返回的字符串形式的响应数据;

        responseXML:后台返回的XML形式的响应数据;

2.6 封装
const ajax = (options) => {
    // 1、创建XMLHttpRequest实例
    let xmlHttp;
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest()
    }else{
        xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
    }

    // 处理请求参数
    const objToString = (obj) => {
        obj._t = new Date().getTime()
        let temp = []
        for(let key in obj){
            // 需要将key和value转成非中文的形式,因为url不能有中文。
            temp.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
        }
        return temp.join("&")
    }
    let params = objToString(options.data || {})

    // 2、构建请求(设置请求方式和请求地址)
    if(options.type.toLowerCase() === 'get'){
        xmlHttp.open(options.type, `${options.url}?${params}`, true)
        // 3、发送请求
        xmlHttp.send()
    }else if(options.type.toLowerCase() === 'json'){
        xmlHttp.open('POST', options.url, true)
        xmlHttp.setRequestHeader('Content-type', 'application/json')
        xmlHttp.send(JSON.stringify(options.data || {}))
    }else{
        xmlHttp.open(options.type, options.url, true)
        xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        xmlHttp.send(params)
    }

    // 4、监听状态变化
    xmlHttp.onreadystatechange = () => {
        if(xmlHttp.readyState == 4){
            // 5、处理返回结果
            if(xmlHttp.status >= 200 && xmlHttp.status < 300){
                options.success(xmlHttp.responseText)
            }else{
                options.fail(xmlHttp.responseText)
            }
        }
    }

    // 设置超时时间
    if (options.timeout) {
        timer = setTimeout(function () {
            xmlHttp.abort(); //中断请求
        }, options.timeout);
    }
}

ajax({
    type: 'get',
    url: 'http://localhost:8080/api/getUserList.do',
    data: { a: 123 },
    timeout: 1000,
    success: data => {
        console.log('success', data);
    },
    fail: err => {
        console.log('error', err);
    },
});

3、总结

        可以发现,ajax只是一种异步请求的方式,并不特指某一种具体的实现方式,但随着使用这种方式实现网络请求时内部又包含请求的情况,就会出现回调地狱,这也是XHR的诟病之一,因此,后来才催生了更加优雅的请求方式(fetch跟axios)。

你可能感兴趣的:(javascript,ajax,开发语言,前端)