手写ajax

68 阅读1分钟

听说面试题会被问到这个,搜索一下拿了个简易版的。

简易版

var request = new XMLHttpRequest();
request.open("GET", "/a/b/c?name=ff", true);
request.onreadystatechange = function () {
  if (request.readyState === 4 && request.status === 200) {
    console.log(request.responseText);
  }
};
request.send();

更加精炼的

var request = new XMLHttpRequest();
request.open("GET", "/a/b/c?name=ff", true);
request.onload = () => console.log(request.responseText);
request.send();

秉着我个人不弄懂不舒服的性子,我又去看了看详情的版本。 我这里按着我个人写代码的思路总结一下。(低版本的IE我不考虑了)

graph LR
    A[创建异步对象] -->B
    B[设置请求地址] -->C
    C[发送请求] -->D
	D[监听状态] -->E
	E[处理结果]

5个步骤,接下来开始写代码。

var xmlhttp = new XMLHttpRequest();
  1. method 是 GET/POST 中的一个 url 是请求的地址 第三个参数是 async 一个可选的布尔参数,表示是否异步执行操作,默认为true。
xmlhttp.open(method,url,true)
  1. 需要区分一下 method 处理方式是不一样的。
if (method.trim().toUpperCase() === "GET") {
	xmlhttp.send(null);
} else if (method.trim().toUpperCase() === "POST") {
    xmlhttp.setRequestHeader(
      "Content-type",
      "application/x-www-form-urlencoded"
    );
	xmlhttp.send(dataToString(data));
}
  1. 监听
  2. 处理 都放在一起了
xmlhttp.onreadystatechange = function () {
  clearTimeout(timer);
  if (xmlhttp.readyState === 4) {
   	 if (
   	   (xmlhttp.status >= 200 && xmlhttp.status < 300) ||
  	    xmlhttp.status === 304
 	   ) {
      	success(xmlhttp); //成功后回调;
      } else {
		error(xmlhttp); //失败后回调;
	  }
  }
}

说实话 拆开来看我自己都看的都是一头雾水。。。

完整代码

function myAjax({ method, url, data, timeout, success, error } = {}) {
  //处理data
  function dataToString(data) {
    data.t = new Date().getTime();
    var res = [];
    for (var key in data) {
      //需要将key和value转成非中文的形式,因为url不能有中文。使用encodeURIComponent();
      res.push(encodeURIComponent(key) + " = " + encodeURIComponent(data[key]));
    }
    return res.join("&");
  }

  // 1.创建对象。
  var xmlhttp = new XMLHttpRequest();

  // 2.设置请求地址
  xmlhttp.open(method, url);

  // 3.发送请求
  if (method.trim().toUpperCase() === "GET") {
    xmlhttp.send(null);
  } else if (method.trim().toUpperCase() === "POST") {
    // POST需要设置header
    xmlhttp.setRequestHeader(
      "Content-type",
      "application/x-www-form-urlencoded"
    );
    xmlhttp.send(dataToString(data));
  }

  // 4.监听状态变化的回调函数
  xmlhttp.onreadystatechange = function () {
    clearTimeout(timer);
    if (xmlhttp.readyState === 4) {
      if (
        (xmlhttp.status >= 200 && xmlhttp.status < 300) ||
        xmlhttp.status === 304
      ) {
        // 5.成功后回调
        success(xmlhttp);
      } else {
        // 5.失败后回调
        error(xmlhttp);
      }
    }
  };

  //判断外界是否传入了超时时间
  if (option.timeout) {
    timer = setInterval(function () {
      xmlhttp.abort(); //中断请求
      clearInterval(timer);
    }, timeout);
  }
}