AJAX 知识点总结

119 阅读3分钟

常见 http 状态码

状态码为三位数,分成五类,数字第一位代表分类,范围就是100 ~ 599

1xx:提示信息,表示目前是协议处理的中间状态,还需要后续的操作

2xx: 成功,报文已经收到并被正确处理

  • "200 OK" 表示请求成功,服务器如客户端所期望的那样返回了处理结果
  • "204 No Content" 表示请求成功,但响应体没有数据
  • "206 Partial Content" 表示请求成功,但响应体只有部分数据

3xx:重定向,资源位置发生变动,需要客户端重新发送请求

  • "301 Moved Permanenly" 永久重定向,请求的资源已经不存在了,需要用新的 url 再次访问
  • "302 Found" 暂时重定向,请求的资源还在,但暂时要用另一个 url 访问
  • "304 Not Modified" 缓存重定向,资源未修改,用于缓存控制

4xx:客户端错误,请求报文有误,服务器无法处理

  • "400 Bad Request" 请求报文错误,但具体是什么错误没有明确,只是一个笼统的错误
  • "403 Forbidden" 服务器禁止访问资源。服务器可在 body 里详细说明拒绝请求的原因
  • "404 Not Found" 资源在本服务器上未找到

5xx:服务器错误,服务器在处理请求时内部发生了错误

  • "500 Internal Server Error" 服务器在执行请求时发生了错误
  • "501 Not Implemented" 客户端请求的功能还不支持
  • "502 Bad Gateway" 服务器作为网关或代理时发生了错误
  • "504 Servive Unavailable" 服务器当前很忙,暂时无法响应服务

AJAX 原理

let xhr = new XMLHttpRequest() 
// 开启请求
xhr.open('get')
// 挂载回调,readystate 改变时触发
// xhr 有5个状态
// readystate === 0, 代理被创建,但尚未调用 open() 方法
// readystate === 1, open() 方法已经被调用
// readystate === 2, send() 方法已经被调用,并且头部和状态已经可获得
// readystate === 3, 下载中; responseText 属性已经包含部分数据
// readystate === 4, 下载操作已完成
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        cb(xhr.responseText);
      }
    }
  };
// 发送请求
xhr.send()

promise 封装 AJAX

function Ajax(obj) {
  return new Promise((res, rej) => {
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyStatus === 4 && xhr.status === 200) {
        res(xhr.responseText);
      } else {
        rej({
          errorType: 'onerror',
          xhr,
        });
      }
    };
    if (obj.method === 'POST') {
      xhr.open('POST', obj.url, true);
      xhr.responseType = 'json';
      xhr.setRequestHeader('Accept', 'application/json');
      const postData = JSON.parse(obj.data);
      xhr.send(postData);
    } else if (obj.method === 'GET') {
      const newUrl = (function (url, data) {
        let queryString = url.includes('?') ? '&' : '?';
        for (let key in data) {
          queryString += `${encodeURIComponent(key)}=${encodeURIComponent(
            data[key]
          )}&`;
        }
        return url + queryString.slice(0, -1);
      })(obj.url, obj.data);

      xhr.open('GET', newUrl, true);
      xhr.send();
    }
  });
}

跨域

同源策略:浏览器只允许同源地址请求资源,域名端口协议三者都相同即为同源

常见跨域方法:

  • CORS:服务器端 response header 设置Access-Control-Allow-Origin: *
  • 服务端没有同源策略的限制,可以通过中间件服务器转发请求实现跨域
  • JSONP
    • 浏览器不限制 script 标签请求 js 脚步
    • 浏览器端在 window 上挂载一个回调函数,通过 script.src 将函数名称传给服务端
    • 服务器端发送 js 脚本将数据调用传入回调函数中
    • script 请求成功后执行脚本调用该回调函数,得到服务端传来的数据
(function (window, document) {
 'use strict';
 let jsonp = function (url, data, callback) {
   // 1.data => url searchParams
   for (let key in data) {
     let queryString = url.indexOf('?') === -1 ? '?' : '&';
     queryString += `${key}=${data[key]}&`;
   }

   // 2.将回调函数名加入 url searchParams
   let cb_fn_name = 'my_json_cb' + Math.random().toString().replace(',', '');
   queryString += 'callback=' + cb_fn_name;

   // 3.创建 script 标签加入到页面中
   let scriptEle = document.createElement('script');
   scriptEle.src = url + queryString;

   // 4.挂载回调函数
   window[cb_fn_name] = function (data) {
     callback(data);
     document.body.removeChild(scriptEle);
   };
 };
 window.$jsonp = jsonp;
})(window, document);

优点: 兼容性好

缺点: 只支持 GET 请求(script 只能 get)。