原生JS实现AJAX

什么是Ajax

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),不是新的编程语言,而是一种使用现有标准的新方法,不重新加载整个页面的情况下更新部分页面

Ajax工作原理

image-20200818144249699

XHR(XMLHttpRequiest)

创建XHR对象

新版本的浏览器都支持XHR对象,直接实例化即可var xhr = new XMLHttpRequest();

XHR请求

如果要将数据发送到服务器,使用XMLHttpRequest 对象的 open() 和 send() 方法

open(method, url, async)

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

send(string)

  • string:仅用于 POST 请求发送数据

GET请求

function load() {
  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      document.getElementById("box").innerHTML = xhr.responseText;
    }
  }
  xhr.open('GET', '/promise.js', true);
  xhr.send();
}

声明一个函数,函数中实例化一个XHR实例对象,当xhr的状态改变成相应的状态时,将请求到的文本插入HTML文档中

![QQ录屏20200818150134 00_00_00-00_00_30](https://cdn.easyremember.cn/img/QQ录屏20200818150134 00_00_00-00_00_30.gif)

POST请求过程相同,只是在send中加入要发送的数据

封装

每次请求都要写这一堆东西太过繁琐,将代码抽离出来作为单独的模块

var Ajax = {
  get: function (url,callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        callback(xhr.responseText);
      }
    }
  },
  post: function (url, data, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('POSt', url, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        callback(xhr.responseText);
      }
    }
    xhr.send(data);
  }
}

function load() {
  Ajax.get('/promise.js', (res) => {
    document.getElementById("box").innerHTML = res;
  });
}

get请求传入url和callback,ststus变为200时触发callback

readystate

image-20200818161131622

status

image-20200818161156325

反馈内容

image-20200818161217054

基于Promise封装

var Ajax = {
  get: function (url) {
    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.send();
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status === 0)) {
          resolve(xhr.responseText);
        }
      }
    })
  },
  post: function (url, data) {
    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest();
      xhr.open('POSt', url, true);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 0) {
          resolve(xhr.responseText);
        }
      }
      xhr.send(data);
    })
  }
}

function load() {
  const p = Ajax.get('/promise.js').then(value => {
    console.log(value);
  }).catch(reason => {
    console.log(reason);
  })
}

把异步操作封装到Promise,调用起来相当方便,这样可以请求到数据,但判断状态如果加上else就会走else分支,目前没有找到原因


前端小白