19 Ajax总结

  • Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据
  • Ajax的过程只涉及JavaScriptXMLHttpRequestDOMXMLHttpRequestajax的核心机制

补充(现代做法):实际开发已基本用 fetch API 取代手写 XMLHttpRequest,它基于 Promise,配合 async/await 写法更简洁;需要请求超时 / 取消时用 AbortController。示例:const res = await fetch(url); const data = await res.json();。注意 fetch 默认不带 cookie(需 credentials: 'include'),且仅在网络错误时 reject,HTTP 4xx/5xx 不会 reject,要自行判断 res.ok

19.1 Ajax 有那些优缺点

优点:

  • 通过异步模式,提升了用户体验.
  • 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
  • Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
  • Ajax可以实现动态不刷新(局部刷新)

缺点:

  • 安全问题 AJAX暴露了与服务器交互的细节。
  • 对搜索引擎的支持比较弱。
  • 不容易调试。

19.2 关于http,XMLHttpRequest,Ajax的关系

  • http是浏览器和web服务器交换数据的协议,规范
  • XMLHttpRequest是一个JS对象,是浏览器实现的一组api函数,使用这些函数,浏览器再通过http协议请求和发送数据。
  • Ajax是一种技术方案,但并不是一种新技术,它最核心的就是依赖浏览器提供的XMLHttpRequest对象。用一句话来概括就是我们使用XMLHttpRequest对象来发送一个Ajax请求

19.3 XMLHttpRequest的发展历程是怎样的?

它最开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest标准。标准又分为Level 1Level 2

Level 2相对于Level 1做了很大的改进,具体来说是:

  • 可以设置HTTP请求的超时时间。
  • 可以使用FormData对象管理表单数据。
  • 可以上传文件。
  • 可以请求不同域名下的数据(跨域请求)。
  • 可以获取服务器端的二进制数据。
  • 可以获得数据传输的进度信息。

19.4 使用XMLHttpRequest封装一个get和post请求

get请求

核心就四步:

  1. var xhr = new XMLHttpRequest()
  2. xhr.open('GET', 'http://www.example.com/api/getname', true)
  3. xhr.onreadystatechange = function () {}
  4. xhr.send()

让我们来封装一个简易版的:

    /*
    * xhr的get请求
    * @param url: 请求地址
    * @param params: 请求参数
    * @param onSuccess: 成功回调函数
    * @param onError: 失败回调函数
    */
    function xhrGet (url, params = {}, onSuccess, onError) {
      // 兼容IE6
      var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
      let paramString = formatParams(params);
      // xhr.open的第三个参数isAsync:是否异步 
      xhr.open('GET', `${url}${paramString}`, true);
      xhr.onreadystatechange = function () {
        // console.log(e);
        console.log(this);
        if (this.readyState === 4) {
          if (this.status >= 200 && this.status < 300) {
            onSuccess(this.response);
          } else {
            onError(this.response)
          }
        }
      }
      xhr.send();
    }
    // 处理参数:如将{name: 'lindaidai'}转为'?name=lindaidai'
    function formatParams (params) {
      var paramString = Object.keys(params).map(key => {
        return `${key}=${encodeURIComponent(params[key])}`
      }).join('&');
      return paramString ? `?${paramString}` : ''
    }

(当然上面的兼容IE6估计现在考的不多了,而且我这种写法其实也没啥用,因为如果真是在IE6下的话,后面的Object.keys()等方法也用不了了)

需要注意的是两种状态,一个是readyState,一个是status

readyState请求状态:

  • 0(未初始化):还没有调用 open() 方法。
  • 1(载入):已调用 send() 方法,正在发送请求。
  • 2(载入完成):send() 方法完成,已收到全部响应内容。
  • 3(解析):正在解析响应内容。
  • 4(完成):响应内容解析完成,可以在客户端调用。

status结果状态码:

  • 0 :如果状态是 UNSENTOPENED;或者如果错误标签被设置(例如跨域时)
  • 200 成功
  • 其它HTTP状态码

post请求:

    function xhrPost (url, params, onSuccess, onError) {
      var xhr = new XMLHttpRequest();
      xhr.open('POST', url, true);
      // ajax的默认请求ContentType:text/plain(纯文本)
      xhr.setRequestHeader("Content-Type", "application-x-www-form-urlencode");
      xhr.onreadystatechange = function () {
        if (this.readyState === 4) {
          if (this.status >= 200 && this.status < 300) {
            onSuccess(this.response);
          } else {
            onError(this.response);
          }
        }
      }
      xhr.send(params);
    }
Last Updated:
Contributors: leeguooooo