AJAX

144 阅读5分钟

写在前面

  • 浏览器可以发请求,收响应(地址栏)
  • 浏览器把这个功能暴露给js开发者,让开发者用js来控制浏览器发请求,收响应
  • 于是浏览器在window上加了一个XMLHttpRequest函数,用这个构造函数可以构造出一个XMLHttpRequest对象,JS用这个XMLHttpRequest对象实现发请求和收响应(AJAX)
  • 这次我们用nodejs模拟服务器,AJAX内容不包括服务端的js代码

服务端小知识

  • 以nodejs为例,我们把响应内容放在repose.write()
  • 但我们平常为什么不在repose.write()写东西呢
  • 我们把fs.readFileSync('public/index.html')写在write里相当于把整个文件夹当成字符串写在write中,和直接写是一样的(因为直接写也写在双引号当中的)
  • 注意HTML文件中的引用scriptlink中路径要与nodejs中的path一致才行

AJAX概念

AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词

加载css

加载css的两种方式

  • 利用html中的link和serve.js中的path相结合,加载出css
  • 利用AJAX加载css
  • AJAX四个步骤
  1. 创建 XMLHttpRequest 实例,使用它的open方法
  2. 发出 HTTP 请求 ,监听它的成功失败
  3. 接收服务器传回的数据
  4. 更新网页数据

AJAX获取文件

getCss.onclick = () => {
  const request = new XMLHttpRequest();
  request.open("GET", "/public/style.css");
  request.onload = () => {
    console.log("success");
};

  request.onerror = () => {
    console.log("fail");
  };

  request.send();
};
  • 此时用js构造了一个HTTP请求,请求/public/style.css文件
  • /public/style.css的路径是与服务端的路径是一致的很好理解,因为请求就是送往服务端的,请求的路径是服务端的一个路由(if else)才有意义
  • 对比link方式,在HTML中发送请求,响应发送给浏览器,浏览器插到link,src位置
  • 而利用AJAX方式浏览器请求成功得到了响应内容,却没有放置它(onload里只是打了一个success没有进一步行动),响应发送给浏览器
  request.onload = () => {
    console.log("success");
    const style = document.createElement('style')
    style.innerHTML = request.response
    document.head.appendChild(style)

};
  • onload中这样写,请求成功才有意义
  • 所有的请求浏览器都会得到一个文件,区别在于普通方法浏览器会直接插到src位置,AJAX还需要对
    new XMLHttpRequest().open("GET","/public/2.js").response
    即浏览器得到的文件,进行操作
  • 普通方法:刚开始下载HTML,看到link发起请求,服务端得到请求,返回响应,浏览器接受响应,下载CSS,浏览器得到css文件,插到link处,开始解析
  • AJAX:下载HTML,下载js代码看到new XMLHttpRequest()发起请求,服务器看到请求返回响应,浏览器接受响应,浏览器得到css文件,并没有插入到相应位置,待解析
  • AJAX还需对得到的文件手动插入,比如js代码写在加载完成时插入

onload&onerror

  • 他俩不能很好地匹配AJAX,比如输错路径返回404不是error
  • XMLHttpRequest.onreadystatechange更专业是个回调函数当浏览器察觉到变化时浏览器才会调用,所以可以写在send()前面,却判断readyState是否等于4
  • XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个:
状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
3 LOADING 下载中; responseText 属性已经包含部分数据。
4 DONE 下载操作已完成。
  • 0:未初始化
  • 1:open方法成功调用以后,请求等待发送
  • 2:send() 方法已经被调用,服务器已经应答客户端的请求,请求已经发送
  • 3:交互中。Http头信息已经接收,响应数据尚未接收。接受第一个响应信息出现时
  • 4:完成。数据接收完成

  • 上面顺序下来就是一个请求的一生
  • 一边下载一边显示
  • XMLHttpRequest.onreadystatechange属性指向一个监听函数。readystatechange事件发生时(实例的readyState属性变化),就会执行这个属性。是一个回调函数,浏览器看到这一行代码是不会立即调用的

  • 如果路径错误(404)readystatec仍会经历3,4阶段,即把失败下载完了
  • 我们可以通过判断new XMLHttpRequest().status,是否为404即可知道路径是否正确
  • XMLHttpRequest.status属性返回一个整数,表示服务器回应的 HTTP 状态码。
  • 那么结合起来两个if,外面判断readyState,里面判断status
request.onreadystatechange = () => {
  //下载完成,但不知道是成功2xx还是失败4Xx 5xx
  if ((request.readyState = 4)) {
    if (request.status >= 200 && request.status < 300) {
      //创建style标签
      const style = document.createElement("style");
      //填写style内容
      style.innerHTML = request.response;
      //插到头里面
      document.head.appendChild(style);
    } else {
      alert("加载CSS失败");
    }
  }
};

区别

  • XMLHttpRequest.response属性表示服务器返回的数据体(即 HTTP 回应的 body 部分),它可能是任何数据类型,比如字符串、对象、二进制对象等等,具体的类型由XMLHttpRequest.responseType属性决定。默认为text即字符串,因为服务器write的就是字符串,正好innerHTML接口是接受字符串的
  • XMLHttpRequest.responseXML属性返回从服务器接收到的 HTML 或 XML 文档对象,该属性为只读。如果本次请求没有成功,或者收到的数据不能被解析为 XML 或 HTML,该属性等于null。返回的是一个DOM对象
  • XMLHttpRequest.responseXML该属性生效的前提是 HTTP回应的Content-Type头信息等于text/xml或application/xml。


总结

  • http什么都可以请求,css,js,html,xml...记得设置正确content-type
  • 我们用AJAX得到的还没有经过解析,得到CSS之后生成style标签,得到JS之后生成script标签,得到HTML之后使用innerHTML和DOM API,得到XML之后使用responseXML和DOM API不同类型的数据有不同类型的解析办法
  • 注意:下载和加载是同时的,发送请求起接受响应,下载响应内容和显示是同时的

注意

  • 有一点值得注意,我们在判断request.readyState = 4``request.status >= 200时是为了让我们解析response
  • 我们在条件里做的就是为了解析