谈谈AJAX(一)

作者: JaniceZD | 来源:发表于2019-06-25 17:38 被阅读4次

    1. 概述

    浏览器与服务器之间,采用 HTTP 协议通信。用户在浏览器地址栏键入一个网址,或者通过网页表单向服务器提交内容,这时浏览器就会向服务器发出 HTTP 请求。

    2005年2月,AJAX 这个词第一次正式提出,它是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。
    后来,AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词,也就是说,只要用脚本发起通信,就可以叫做 AJAX 通信。

    具体来说,AJAX 包括以下几个步骤。

    1. 创建 XMLHttpRequest 实例
    2. 发出 HTTP 请求
    3. 接收服务器传回的数据
    4. 更新网页数据

    概括起来,就是一句话,AJAX 通过原生的 XMLHttpRequest 对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理。

    一旦拿到服务器返回的数据,AJAX 不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在做的事情。

    注意,AJAX 只能向同源网址(协议、域名、端口都相同)发出 HTTP 请求,如果发出跨域请求,就会报错。

    2. 如何发请求?(背景)

    form 可以发请求,但是会刷新页面或新开页面
    a 可以发 get 请求,但是也会刷新页面或新开页面
    img 可以发 get 请求,但是只能以图片的形式展示
    link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示
    script 可以发 get 请求,但是只能以脚本的形式运行

    提出需求:如何不受限制的发请求?

    • get post delete请求都行
    • 想以什么形式展示就以什么形式展示

    3. 微软的突破

    IE 5 率先在 JS 中引入 ActiveX 对象(API),使得 JS 可以直接发起 HTTP 请求。
    随后 Mozilla、 Safari、 Opera 也跟进(抄袭)了,取名 XMLHttpRequest,并被纳入 W3C 规范。

    可这样使用XMLHttpRequest:
    var x = new XMLHttpRequest()
    

    注意:XMLHttpRequest 是 window下的全局对象

    4. AJAX(异步的 JavaScript 和 XML)

    Jesse James Garrett 将如下技术点的方案取名叫做 AJAX:异步的 JavaScript 和 XML

    1. 使用 XMLHttpRequest 发请求
    2. 服务器返回 XML 格式的字符串(如今用JSON代替了XML)
    3. JS 解析 XML,并更新局部页面

    5. 如何使用 XMLHttpRequest

    5.1 XMLHttpRequest对象用法例子

    客户端代码:

    let request = new XMLHttpRequest();  //创建一个XMLHttpRequest
    
    request.onreadystatechange = function(){
      // 通信成功时,状态值为4
      if (request.readyState === 4){
        if (request.status === 200){
          console.log(request.responseText);
        } else {
          console.error(request.statusText);
        }
      }
    };
    
    request.onerror = function (e) {
      console.error(request.statusText);
    };
    
    request.open('GET', '/endpoint', true); //配置
    request.send(null);  //发送
    

    服务器端代码:

    if(path === '/'){
        response.statusCode = 200
        let string = fs.readFileSync('./index.html') 
        response.setHeader('Content-Type', 'text/html;charset=utf-8')
        response.write(string)
        response.end()
      }
    
    • http 请求的路径都是绝对路径.所以都是以 / 开头
    • 设置响应头中的Content-Type,response.setHeader('Content-Type', 'text/html;charset=utf-8'),即要求浏览器以HTML的语法解析这段字符串!
    • 对于HTTP来说,响应的第四部分始终都是字符串,因为response.write(string)返回的是字符串,我们给浏览器返回了符合html格式的字符串。

    5.2 XMLHttpRequest 的实例属性

    • XMLHttpRequest.readyState
      XMLHttpRequest.readyState返回一个整数,表示实例对象的当前状态。该属性只读。
      4,表示服务器返回的数据已经完全接收,或者本次接收已经失败。
      通信过程中,每当实例对象发生状态变化,它的 readyState 属性的值就会改变。
    var xhr = new XMLHttpRequest();
    
    if (xhr.readyState === 4) {
      // 请求结束,处理服务器返回的数据
    } else {
      // 显示提示“加载中……”
    }
    

    上面代码中,xhr.readyState 等于 4 时,表明脚本发出的 HTTP 请求已经完成。其他情况,都表示 HTTP 请求还在进行中。

    • XMLHttpRequest.onreadystatechange
      实例的 readyState属性变化,就会执行这个属性。
    • XMLHttpRequest.responseText
      XMLHttpRequest.responseText 属性返回从服务器接收到的字符串,该属性为只读。
    • XMLHttpRequest.status
      XMLHttpRequest.status属性返回一个整数,表示服务器回应的 HTTP 状态码。
      基本上,只有2xx和304的状态码,表示服务器返回是正常状态。
    if (xhr.readyState === 4) {
      if ( (xhr.status >= 200 && xhr.status < 300)
        || (xhr.status === 304) ) {
        // 处理服务器的返回数据
      } else {
        // 出错
      }
    }
    

    6. 使用JSON解析响应的第四部分

    XML语言结构的数据不好用且已经过时了,现使用JSON替代XML。
    JSON是一门数据格式化语言,用来表示数据。
    JSON官网:JSON

    6.1 语法快速过

    1. JS的数据类型仅剩 symbolundefinedfunction 没抄
    2. 铁轨图(从左往右看)
      JS      VS      JSON
    undefined         没有
    null              null
    'janice'          "janice"
    ['a','b']         ["a","b"]
    {name: 'janice'}  {"name":"janice"}
    function fn(){}   没有
    var a = {}        搞不定(没有变量)
    a.self = a        搞不定(没有变量)
    {__proto__}       没有原型链
    

    区别:

    • JSON没有抄袭 functionundefined
    • JSON的字符串 string首尾必须是 双引号 "

    6.2 如何使用JSON

    if (path === '/xxx') {
      response.statusCode = 200
      response.setHeader('Content-Type', 'text/json;charset=utf-8')
      response.write(`
      {
        "note":{
          "to": "Rose",
          "from": "Jack",
          "heading": "经典片段",
          "content": "You jump,I jump."
        }
      }
      `)
      response.end()
    }
    

    服务器返回的是字符串,恰巧这个字符串刚好符合JSON对象的语法格式。

    前端收到响应后:

    if(request.status >= 200 && request.status < 300){
      console.log('说明请求成功')
      let string = request.responseText
      // 把符合 JSON 语法的字符串转换成 JS 对应的值
      let object = window.JSON.parse(string) 
      // JSON.parse 是浏览器提供的
    }else if(request.status >= 400){
      console.log('说明请求失败') 
    }
    

    7. 同源策略

    只有 协议+端口+域名 一模一样才允许发 AJAX 请求

    1. http://baidu.com 可以向 http://www.baidu.com 发 AJAX 请求吗 no
    2. http://baidu.com:80 可以向 http://baidu.com:81 发 AJAX 请求吗 no

    浏览器必须保证:
    只有 协议+端口+域名 一模一样才允许发 AJAX 请求
    CORS 可以告诉浏览器,我俩一家的,别阻止他

    8. CORS 跨域

    CORS(Cross-origin resource sharing),全称是“跨域资源共享”,是一个 W3C 标准。它允许浏览器向跨域的服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。

    在代码中添加CORS头即可跨域:

    if (path === '/xxx') {
      response.statusCode = 200
      response.setHeader('Content-Type', 'text/json;charset=utf-8')
      response.setHeader('Access-Control-Allow-Origin', 'http://frank.com:8001')
      response.write(`
      {
        "note":{
          "to": "Rose",
          "from": "Jack",
          "heading": "经典片段",
          "content": "You jump,I jump."
        }
      }
      `)
      response.end()
    }
    

    注意:JSONP不能发起POST请求,要POST只能用CORS

    彩蛋

    面试问题:请使用原生JS发送Ajax请求

    mybutton.addEventListener('click', (e) => {
      let request = new XMLHttpRequest()
      request.open('get', 'http://jack.com:8002/xxx')  
      //配置request 参数分别为方法和路径
      request.send()
      request.onreadystatechange = () => {
        if (request.readyState === 4) {
          if (request.status >= 200 && request.status < 300) {
            // 把符合 JSON 语法的字符串转换成 JS 对应的值
            let string = request.responseText
            // JSON.parse 是浏览器提供的
            let object = window.JSON.parse(string)
            console.log(object.note)
          } else if (request.status >= 400) {
            console.log('请求失败')
          }
        }
      }
    })
    

    参考链接

    1. 阮一峰,JavaScript 教程—XMLHttpRequest 对象
    2. 写代码啦

    相关文章

      网友评论

        本文标题:谈谈AJAX(一)

        本文链接:https://www.haomeiwen.com/subject/apunqctx.html