📠 一、Ajax(XHR)

1、Ajax

Ajax:全称 Asynchronous JavaScript + XML(异步 JavaScript 和 XML)

  • Ajax 出现前,任何和服务器的交互都需要刷新页面,用户体验非常差
  • Ajax 出现后,网页应用能够快速地将增量更新呈现在用户界面上,不需重载(刷新)整个页面

2、XHR

浏览器的 XMLHttpRequest 是实现 Ajax 最重要的对象,let xhr = new XMLHttpRequest();创建一 xhr 实例

  • 方法

    • open:初始化一个请求。xhr.open(method, url, async);
    • send:发送 HTTP 请求。xhr.send(param);
    • abort:终止一个 ajax 请求。xhr.abort(),readyState 将被设置为 0
    • setRequestHeader:设置 http 请求头。xhr.setRequestHeader(header, value);在 open()、send()间调用
    • getResponseHeader:获取 http 返回头。let header= xhr.getResponseHeader(name);
  • 属性

    • readyState:标识当前 XMLHttpRequest 对象所处的状态
    • status:表示 http 请求的状态, 初始值为 0。如果服务器没有显式地指定状态码, 那么 status 将被设置为默认值, 即 200。
    • responseType:表示响应的数据类型,并允许我们手动设置,如果为空,默认为 text 类型
    • response:返回响应的正文
    • withCredentials:withCredentials 的属性为 true 将允许携带跨域 cookie
  • 事件回调

    • onreadystatechange:当 readyState 属性发生变化时,callback 会被触发。
    • onloadstart:在 ajax 请求发送之前(readyState==1 后, readyState==2 前),callback 会被触发。
    • onprogress:回调函数可以获取资源总大小 total,已经加载的资源大小 loaded,用这两个值可以计算加载进度。

      • xhr.onprogress = function(event){console.log(event.loaded / event.total);}
    • onload:当一个资源及其依赖资源已完成加载时,将触发 callback,通常我们会在 onload 事件中处理返回值
  • 异常处理

    • onerror:当 ajax 资源加载失败时会触发 callback。
    • ontimeout:当进度由于预定时间到期而终止时,会触发 callback,超时时间可使用 timeout 属性进行设置。
  1. let xhr = new XMLHttpRequest();
  2. xhr.open("GET", "/my/url");
  3. xhr.withCredentials = true;
  4. xhr.setRequestHeader("Content-Type", "application/json");
  5. xhr.responseType = "json";
  6. xhr.send();
  7. xhr.onload = function () {
  8. if (xhr.status != 200) {
  9. // HTTP 出错?
  10. // 处理错误
  11. alert("Error: " + xhr.status);
  12. return;
  13. }
  14. // 从 xhr.response 中获取响应
  15. };
  16. xhr.onerror = function () {
  17. console.log("Network request failed");
  18. };

🏄二、Fetch

Fetch API 是一个用于访问和操纵 HTTP 管道的强大的原生 API

1、请求

浏览器立即发送请求,并返回一个 promise

  1. const options = {
  2. method: "POST",
  3. mode: "cors" // 跨域
  4. headers: {
  5. "Content-Type": "application/json"
  6. }, // 设置请求头
  7. body: JSON.stringify({ name: "123" }), // 请求参数
  8. credentials: "include", // 需发送凭据
  9. };
  10. let promise = fetch(url, options);

2、获取响应状态并解析响应体

  • 属性

    • response.ok —— 布尔值,若 HTTP 状态码在 200-299 之间,返回 true
    • response.status —— HTTP 状态码
    • response.headers —— 类似于 Map 的 headers 对象,可获取单个或迭代它们
    • response.body —— ReadableStream 对象,允许逐块读取正文,追踪 download 过程

      • 启动 fetch 并赋值给 reader(流读取器):

        • const reader = response.body.getReader();
      • 从 Content-Length 头中找出完整响应长度,获得总长度(总块数)

        • const contentLength = +response.headers.get('Content-Length');
      • 读取数据,调用await reader.read()直到它已经完成
      • 将块合并成单个Uint8Array字节块
      • 解码成字符串
  • 方法:Response 提供了多种基于 promise 方法来获取不同格式的响应正文

    • response.json() —— 将 response 解析为 JSON 对象
    • response.text() —— 以文本形式返回 response
    • response.formData() —— 以 FormData 对象(form/multipart 编码)的形式返回 response
    • response.blob() —— 以 Blob(具有类型的二进制数据)形式返回 response
    • response.arrayBuffer() —— 以 ArrayBuffer(纯二进制数据)形式返回 response
  1. //await方法
  2. let response = await fetch(url, options); //解析 response headers
  3. if (response.ok) {
  4. // 如果 HTTP 状态码在 200-299 之间,获取响应体(如下所示)
  5. let result = await response.json(); // 以 JSON 形式读取数据
  6. console.log(result);
  7. } else {
  8. alert("HTTP-Error: " + response.status);
  9. }
  10. //纯 promise 方法
  11. fetch(url, options)
  12. .then((response) => response.json())
  13. .then((result) => {
  14. console.log(result);
  15. }) // 响应数据
  16. .catch((err) => {
  17. console.log(err);
  18. }); // 异常处理

3、中止(abort)

一个特殊的内置对象:AbortController。可扩展的,它允许同时取消多个 fetch

  1. // 1 秒后中止
  2. let controller = new AbortController();
  3. setTimeout(() => controller.abort(), 1000);
  4. try {
  5. let response = await fetch(url, {
  6. signal: controller.signal,
  7. });
  8. } catch (err) {
  9. if (err.name == "AbortError") {
  10. // handle abort()
  11. alert("Aborted!");
  12. } else {
  13. throw err;
  14. }
  15. }

🎷三、Axios

axios 功能:从浏览器中创建 XMLHttpRequests、从 node.js 创建 http 请求、支持 Promise API、拦截请求和响应、转换请求数据和响应数据、取消请求、自动转换 JSON 数据、客户端支持防御 XSRF

1、axios API

  • axios(config)
  1. // GET request for remote image
  2. axios({
  3. method: "get",
  4. url: "http://bit.ly/2mTM3nY",
  5. responseType: "stream",
  6. }).then(function (response) {
  7. response.data.pipe(fs.createWriteStream("ada_lovelace.jpg"));
  8. });
  • axios(url[,config]):axios('/user/12345');// Send a GET request (default)

2、别名请求方法

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

3、请求配置选项

  1. {
  2. url: '/user',
  3. method: 'get', // default
  4. baseURL: 'https://some-domain.com/api/',
  5. transformRequest: [function (data, headers) {
  6. // transformRequest方法允许在请求发送到服务器之前修改该请求
  7. // 只适用于PUT、POST、PATCH方法中
  8. // 最后必须返回一个string、ArrayBuffer或者Stream。
  9. return data;
  10. }],
  11. transformResponse: [function (data) {
  12. // transformResponse方法允许在数据传递到then/catch之前修改response数据
  13. // 此方法最后也要返回数据
  14. return data;
  15. }],
  16. headers: {'X-Requested-With': 'XMLHttpRequest'},// 发送自定义Headers头文件
  17. params: {
  18. ID: 12345
  19. },// 发送请求的查询参数对象,拼接成 url?param1=value1&param2=value2
  20. data: {
  21. firstName: 'Fred'
  22. },// data是在发送POST、PUT或者PATCH请求的数据对象
  23. timeout: 1000, // default is `0` (no timeout)
  24. withCredentials: false, // default
  25. adapter: function (config) {
  26. /* adapter允许用户处理更易于测试的请求。返回Promise和一个有效的response */
  27. },
  28. auth: {
  29. // auth表明提供凭证用于完成http的身份验证。
  30. //这将会在headers中设置一个Authorization授权信息。
  31. //自定义Authorization授权要设置在headers中
  32. username: 'janedoe',
  33. password: 's00pers3cret'
  34. },
  35. responseType: 'json', // default
  36. responseEncoding: 'utf8', // default
  37. xsrfCookieName: 'XSRF-TOKEN', // default
  38. xsrfHeaderName: 'X-XSRF-TOKEN', // default
  39. onUploadProgress: function (progressEvent) {
  40. // Do whatever you want with the native progress event
  41. },
  42. onDownloadProgress: function (progressEvent) {
  43. // Do whatever you want with the native progress event
  44. },
  45. maxContentLength: 2000,
  46. validateStatus: function (status) {
  47. return status >= 200 && status < 300; // default
  48. },
  49. maxRedirects: 5, // default
  50. socketPath: null, // default
  51. httpAgent: new http.Agent({ keepAlive: true }),
  52. httpsAgent: new https.Agent({ keepAlive: true }),
  53. proxy: {
  54. host: '127.0.0.1',
  55. port: 9000,
  56. auth: {
  57. username: 'mikeymike',
  58. password: 'rapunz3l'
  59. }
  60. },
  61. cancelToken: new CancelToken(function (cancel) {
  62. })
  63. }

4、响应信息

  1. {
  2. // `data` is the response that was provided by the server
  3. data: {},
  4. status: 200,
  5. statusText: 'OK',
  6. headers: {},
  7. config: {},
  8. request: {}
  9. }

5、拦截器

  1. // Add a request interceptor
  2. axios.interceptors.request.use(
  3. function (config) {
  4. // Do something before request is sent
  5. return config;
  6. },
  7. function (error) {
  8. // Do something with request error
  9. return Promise.reject(error);
  10. }
  11. );
  12. // Add a response interceptor
  13. axios.interceptors.response.use(
  14. function (response) {
  15. // Any status code that lie within the range of 2xx cause this function to trigger
  16. // Do something with response data
  17. return response;
  18. },
  19. function (error) {
  20. // Any status codes that falls outside the range of 2xx cause this function to trigger
  21. // Do something with response error
  22. return Promise.reject(error);
  23. }
  24. );
  25. //delete interceptor
  26. const myInterceptor = axios.interceptors.request.use(function () {
  27. /*...*/
  28. });
  29. axios.interceptors.request.eject(myInterceptor);
  30. //add interceptors to a custom instance of axios.
  31. const instance = axios.create();
  32. instance.interceptors.request.use(function () {
  33. /*...*/
  34. });

👿四、Fetch、Axios 区别实例

post 请求

  • Fetch 实现:url作为第一参数;配置项body属性提供需传输的数据,且需JSON.stringify手动序列化;获取响应数据使用response.json()
  1. let url = "https://someurl.com";
  2. let options = {
  3. method: "POST",
  4. mode: "cors",
  5. headers: {
  6. Accept: "application/json",
  7. "Content-Type": "application/json;charset=UTF-8",
  8. },
  9. body: JSON.stringify({
  10. property_one: value_one,
  11. property_two: value_two,
  12. }),
  13. };
  14. //await方法
  15. let response = await fetch(url, options);
  16. if (response.ok) {
  17. let data = await response.json();
  18. // do something with data
  19. } else {
  20. alert("HTTP-Error: " + response.status);
  21. }
  22. //promise方法
  23. fetch(url, options)
  24. .then((response) => response.json())
  25. .then((data) => {
  26. console.log(data);
  27. })
  28. .catch((err) => {
  29. console.log(err);
  30. });
  • Axios 实现:配置项作为唯一对象参数,包含urldata属性提供需传输的数据,不需手动序列化;获取响应数据使用response.data
  1. let url = "https://someurl.com";
  2. let options = {
  3. method: "POST",
  4. url: url,
  5. headers: {
  6. Accept: "application/json",
  7. "Content-Type": "application/json;charset=UTF-8",
  8. },
  9. data: {
  10. property_one: value_one,
  11. property_two: value_two,
  12. },
  13. };
  14. //await方法
  15. let response = await axios(options);
  16. if (response.status === 200 && response.statusText === "OK") {
  17. let data = await response.data;
  18. // do something with data
  19. }
  20. //promise方法
  21. axios(options)
  22. .then((response) => response.data)
  23. .then((data) => {
  24. console.log(data);
  25. })
  26. .catch((err) => {
  27. console.log(err);
  28. });