美文网首页
26.5、AJAX版本、响应状态、超时设置、同步与异步

26.5、AJAX版本、响应状态、超时设置、同步与异步

作者: 一土二月鸟 | 来源:发表于2020-07-23 22:38 被阅读0次

XMLHttpRequest版本

  • level 1
    • 传输纯文本数据
    • 无法跨域
  • level 2
    • 支持超时时间
    • 支持跨域(需要后端配合设置access-control-allow-origin)
    • 支持二进制数据(文件、formdata对象),可获取进度

响应状态

  • 200 成功
  • 301 永久性移动,浏览器输入了一个网址后,会自动跳转到另一个网址。
  • 302 暂时性移动,浏览器输入一个网址A后,自动跳转到另一个网址B。搜索引擎可能会记录网址A,打开网站后依旧为A。具体参见
  • 304 未修改,使用本地缓存文件。如果etag和modified-since时间相同,则使用本地缓存文件。
  • 307 暂时重定向。参见
  • 400 语法错误,被禁止访问,url拼写错误。
  • 401 未授权。表示缺少认证信息,认证信息可能是账号密码或指定的终端。
  • 403 请求被拒绝。由于服务器目录禁止被操作而返回的错误。
  • 404 找不到访问的资源。
  • 500 服务器端程序发生错误。
  • 503 服务器超负荷运行返回的错误,稍后访问可能会成功。

设置超时

  • timeout 为超时时间,超过后则自动断开连接,但兼容性不是很好。
  xhr.timeout = 100; 

生命周期

  • onloadstart >> readyState === 4 >> onload || onerror || onabort >> onloadend


封装ajax完整版

var $ = function (w) {

  function formatData (data) {
    if(!data) return null;

    var str = '',
        toStr = Object.prototype.toString;

    for( var key in data ) {
      if ( toStr.call(data[key]) === '[object Object]' 
        || toStr.call(data[key]) === '[object Array]' ) {
          // 待实现
      }
      str += key + '=' + data[key] + '&';
    }
    str = str.replace(/&$/, '');
    return str;
  }

  function _doAjax(opt) {
    var xhr = null;
    if (w.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
    } else {
      xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }

    opt = opt || {};

    if (!opt.url) throw new Error("url为必填项");

    let url = opt.url,
      type = (opt.type || 'GET').toUpperCase(),
      data = opt.data || null,
      contentType = opt.contentType || 'application/x-www-form-urlencoded', // 只有post请求时,需要设置请求的数据类型
      dataType = (opt.dataType || 'json').toLowerCase(), // 服务器返回的数据类型
      async = (opt.async + '') === 'false' ? false : true,
      timeout = opt.timeout || 30000, // 如果设置0,默认为30秒 todo:封装其他类型  回调等 
      success = opt.success || function () {},
      error = opt.error || function () {},
      complete = opt.complete || function () {},
      tId = null;


    xhr.onreadystatechange = function () { // 此函数必须在send方法执行前进行定义,否则无法实现同步
      if (xhr.readyState === 4) {

        if (xhr.status === 304 || (xhr.status >= 200 && xhr.status < 300)) {

          switch (dataType) {
            case 'json': 
              success(JSON.parse(xhr.responseText));
              break;
            case 'text':
              success(xhr.responseText);
              break;
            case 'xml':
            case 'html':
              success(xhr.responseXml);
              break;
            default :
              success(xhr.responseText); 
          }

        } else {
          error(xhr.statusText);
        }

        clearTimeout(tId);
        tId = null;
        xhr = null;
        complete("The request of " + url + " has completed");

      }
    }

    tId = setTimeout(function () {
      clearTimeout(tId);
      xhr.abort(); // 终止已发出的请求
      tId = null;
      xhr = null;
      throw new Error('The request has time out');
    }, timeout);

    xhr.open(type, url, async);
    if (type === 'POST') xhr.setRequestHeader('Content-Type', contentType);
    // xhr.setResponseType = dataType;  // TOOD: 待优化,将xml html转为document 设置blob、arrayBuffer、ms-stream、"" 类型
    xhr.send(formatData(data)); // 如果是同步,send方法会等待readyState为4的时候才会继续执行后面的代码
  }

  return {
    ajax: function (options) {
      _doAjax(options);
    },
    post: function (url, data, cb) {
      this.ajax({
        url: url,
        type: 'post',
        data: data,
        success: cb,
      });
    },
    get: function (url, cb) {
      this.ajax({
        url: url,
        success: cb,
      });
    }
  };
}(window);

相关文章

网友评论

      本文标题:26.5、AJAX版本、响应状态、超时设置、同步与异步

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