简洁全面的"手写AJAX,以及用Promise封装AJAX请求",给你一个满分答案

2,578 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

原生js实现Ajax,本文用最简洁的脉路,帮你梳理前端经典面试“手写ajax”,然后再告诉你廖雪峰是如何使用Promise封装ajax!!!

手写AJAX

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        console.log(xhr.responseText)
        // do what
    } else {
        new Error(xhr.statusText)
    }
};
xhr.open("GET", url, true);
xhr.send();

实现AJAX请求的步骤:

  1. 创建 XMLHttpRequest 对象

  2. 设置状态监听函数

  3. 规定请求的类型、URL 以及是否异步处理请求

  4. 将请求发送到服务器

介绍AJAX

AJAX是异步的JavaScript和XML(Asynchronous JavaScript And XML)。简单点说,就是使用 XMLHttpRequest 对象与服务器通信。

AJAX最主要的两个特性:

  • 在不重新加载页面的情况下发送请求给服务器。
  • 接受并使用从服务器发来的数据。

步骤详解

// 1.创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 2.设置状态监听函数
xhr.onreadystatechange = function () {// 状态发生变化时,触发回调函数
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        // 成功:从服务器获取数据,通过responseText拿到响应的文本
        console.log(xhr.responseText)
        // do what
    } else {
        // 失败,根据响应码判断失败原因
        new Error(xhr.statusText)
    }
};
// 3.规定请求的类型、URL 以及是否异步处理请求
xhr.open("GET", url, true);
// 4.将请求发送到服务器
xhr.send();

创建 XMLHttpRequest 对象

创建 XMLHttpRequest 对象的语法

var xhr = new XMLHttpRequest();

向服务器发送请求

将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open()  和 send()  方法:

xhr.open("GET",url,true);
xhr.send();

open(method,url,async) 方法 规定 请求的类型URL 以及 是否异步处理请求

  • method:请求的类型;GET 或 POST
  • url:文件在服务器上的位置
  • async:true(异步)或 false(同步),默认值为true

send(string) 方法 将请求发送到服务器。

  • string:仅用于 POST 请求

如果需要像获取 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:

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

设置状态监听函数

当请求被发送到服务器时,我们需要执行一些基于响应的任务,处理服务器响应。

每当 readyState 改变时,就会触发 onreadystatechange 事件。

readyState 属性存有 XMLHttpRequest 的状态信息。

下面是 XMLHttpRequest 对象的三个重要的属性:

onreadystatechange - 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。

readyState - 存有 XMLHttpRequest 的状态。请求状态 从 0 到 4 发生变化。

  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 请求处理中
  • 4: 请求已完成,且响应已就绪

status - HTTP响应码

  • 200: "OK"
  • 404: 未找到页面

每当 readyState 发生变化时就会调用 onreadystatechange 函数。

当 readyState 等于 4 且状态为 200 时,表示响应已就绪:

// 设置状态监听函数
xhr.onreadystatechange = function () {// 状态发生变化时,触发回调函数
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        // 成功:从服务器获取数据,通过responseText拿到响应的文本
        console.log(xhr.responseText)
        // do what
    } else {
        // 失败,根据响应码判断失败原因
        new Error(xhr.statusText)
    }
};

注意: onreadystatechange 事件被触发 4 次(0 - 4), 分别是: 0-1、1-2、2-3、3-4,对应着 readyState 的每个变化。

错误监控处理

XMLHttpRequest.statusText属性返回一个字符串,表示服务器响应的状态提示。不同于status属性,该属性包含整个状态信息,比如“OK”和“Not Found”。如果请求的状态readyState的值为"0"或者"1",则这个属性的值将会是一个空字符;如果服务器没有返回状态提示,该属性的值默认为“OK”。该属性为只读属性。

从服务器获取数据

当 readyState 等于 4 且状态为 200 时,表示响应已就绪,这个时候就可以用服务器返回的数据做任何你想做的了。

可以通过 xhr.responseText去访问这些数据:

  • xhr.responseText - 服务器以文本字符的形式返回

使用Promise封装AJAX

// Promise封装Ajax请求
function ajax(method, url, data) {
    var xhr = new XMLHttpRequest();
    return new Promise(function (resolve, reject) {
        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200) {
                resolve(xhr.responseText);
            } else {
                reject(xhr.statusText);
            }

        };
        xhr.open(method, url);
        xhr.send(data);
    });
}

使用上面封装好的ajax发起一个请求:

ajax('GET', '/api/categories').then(function (data) {
    // AJAX成功,拿到响应数据
    console.log(data);
}).catch(function (status) {
    // AJAX失败,根据响应码判断失败原因
    new Error(status)
});

参考