Ajax、$、Axios和Fetch

房子昂
2023-12-01

Ajax、Axios和Fetch



前言

面试前复习


一、简介

Ajax

全称Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。

Jquery Ajax

是 jQuery 底层 AJAX 实现。无需直接操作该函数,除非你需要操作不常用的选项,以获得更多的灵活性。

Axios

不是原生JS的,需要进行安装,它不但可以在客户端使用,也可以在nodejs端使用。Axios也可以在请求和响应阶段进行拦截。同样也是基于Promise对象的。
特性:从浏览器中创建 XMLHttpRequests、从 node.js 创建 http 请求、支持 Promise API、拦截请求和响应等。

Fetch

Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。
使之今后可以被使用到更多地应用场景中:无论是service workers、Cache API、又或者是其他处理请求和响应的方式,甚至是任何一种需要你自己在程序中生成响应的方式。
Fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的Promise对象。Fetch是基于promise设计的。
Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js。Fetch函数就是原生js,没有使用XMLHttpRequest对象。

二、实现

1.原生Ajax用ES6类封装

代码如下(示例):

    class Ajax {
    constructor(xhr) {
        xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        this.xhr = xhr;
    }

    send(options) {
        let xhr = this.xhr;

        let opt = {
            type: options.type || 'GET',
            url: options.url || '',
            async: options.async || 'true',
            dataType: options.dataType || 'json',
            questring: options.questring || ''
        };

        return new Promise((resolve, reject) => {
            xhr.open(opt.type,opt.url,opt.async);

            xhr.onreadystatechange = ()  => {
                if(xhr.readyState === 4) {
                    if(xhr.status === 200){
                        if(opt.dataType === 'json'){
                            const data = JSON.parse(xhr.responseText);
                            resolve(data);
                            console.log(data);
                        }
                    }else {
                        reject(new Error(xhr.status || 'Server is fail.'));
                    }
                }
            };
            xhr.onerror = () => {
                reject(new Error(xhr.status || 'Server is fail.'));
            };
            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            xhr.send(opt.questring);
        })
    }
}

四种常见的 POST 提交数据方式

application/x-www-form-urlencoded

浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是application/x-www-form-urlencoded;charset=utf-8

multipart/form-data

我们使用表单上传文件时,就要让 form 的 enctype 等于这个值。

application/json

在json盛行的现在,一般都用它了。

text/xml

相比于JSON,XML不能更好的适用于数据交换,它包含了太多的包装, 而且它跟大多数编程语言的数据模型不匹配,让大多数程序员感到诧异,XML是面向数据的,JSON是面向对象和结构的,后者会给程序员一种更加亲切的感觉。
我们现在一般这样来使用:
1、XML 存储数据,存储配置文件等需要结构化存储的地方使用;
2、数据传输、数据交互使用JSON;

2.jQuery实现Ajax

代码如下(示例):

$(".btn").click(function () {
           $.ajax({
               url: "test.php",
               type: "post",
               data: {
                   username: $("#username").val(),
                   pwd: $("#psw").val()
               },
               dataType: "JSON",
               success: function (data) {
                   console.log(data.msg);
               },
               error: function (jqXHR) {
                   alert("错误码:" + jqXHR.status);
               }
           })
       })

3.Axios实现

代码如下(示例):

npm install axios
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// 可选地,上面的请求可以这样做
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

  // 执行 POST 请求
  axios
    .post("/user", {
      firstName: "Fred",
      lastName: "Flintstone",
    })
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });

// 执行多个并发请求
function getUserAccount() {
  return axios.get("/user/12345");
}

function getUserPermissions() {
  return axios.get("/user/12345/permissions");
}

axios.all([getUserAccount(), getUserPermissions()]).then(
  axios.spread(function (acct, perms) {
    // 两个请求现在都执行完成
  })
);

// axios API
// 可以通过向 axios 传递相关配置来创建请求
// 发送 POST 请求
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});
// 发送 GET 请求(默认的方法)
axios('/user/12345');

4.Fetch实现

Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

这种功能以前是使用 XMLHttpRequest 实现的。Fetch 提供了一个更理想的替代方案,可以很容易地被其他技术使用,例如 Service Workers (en-US)。Fetch 还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。

请注意,fetch 规范与 jQuery.ajax() 主要有三种方式的不同:

当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
fetch() 可以不会接受跨域 cookies;你也可以不能使用 fetch() 建立起跨域会话。其他网站的 Set-Cookie 头部字段将会被无视。
fetch 不会发送 cookies。除非你使用了credentials 的初始化选项。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为 same-origin。Firefox 也在 61.0b13 版本中进行了修改)

代码如下(示例):

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

使用 fetch() POST JSON数据

var url = 'https://example.com/profile';
var data = {username: 'example'};

fetch(url, {
  method: 'POST', // or 'PUT'
  body: JSON.stringify(data), // data can be `string` or {object}!
  headers: new Headers({
    'Content-Type': 'application/json'
  })
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

可以通过 HTML 元素,FormData() 和 fetch() 上传文件。

var formData = new FormData();
var fileField = document.querySelector("input[type='file']");

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
  method: 'PUT',
  body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

可以通过HTML 元素,FormData() 和 fetch() 上传文件。

var formData = new FormData();
var photos = document.querySelector("input[type='file'][multiple]");

formData.append('title', 'My Vegas Vacation');
// formData 只接受文件、Blob 或字符串,不能直接传递数组,所以必须循环嵌入
for (let i = 0; i < photos.files.length; i++) {
    formData.append('photo', photos.files[i]);
}

fetch('https://example.com/posts', {
  method: 'POST',
  body: formData
})
.then(response => response.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));


各自优缺点

axios

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

XSRF(Cross Site Request Forgery, 跨站域请求伪造)也称 XSRF, 是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入,跨站域脚本攻击等在近年来已经逐渐为众人熟知,很多网站也都针对他们进行了防御。然而,对于大多数人来说,CSRF 却依然是一个陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在着 CSRF 漏洞,从而被黑客攻击而使 Gmail 的用户造成巨大的损失。客户端支持防御 XSRF,是怎么做到的呢,就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。

axios创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。请求配置传送门

Axios既提供了并发的封装,体积也较小,也没有下文会提到的fetch的各种问题,当之无愧是现在最应该选用的请求的方式。

fetch

1.语法简洁,更加语义化
2.基于标准 Promise 实现,支持 async/await
3.同构方便,使用 isomorphic-fetch
4.更加底层,提供的API丰富(request, response)
5.脱离了XHR,是ES规范里新的实现方式

fetch在前端的应用上有一项xhr怎么也比不上的能力:跨域的处理

我们都知道因为同源策略的问题,浏览器的请求是可能随便跨域的——一定要有跨域头或者借助JSONP,但是,fetch中可以设置mode为"no-cors"(不跨域),如下所示:

fetch('/users.json', {
    method: 'post', 
    mode: 'no-cors',
    data: {}
}).then(function() { /* handle response */ });

这样之后我们会得到一个type为“opaque”的返回。需要指出的是,这个请求是真正抵达过后台的,所以我们可以使用这种方法来进行信息上报,在我们之前的image.src方法中多出了一种选择,另外,我们在network中可以看到这个请求后台设置跨域头之后的实际返回,有助于我们提前调试接口(当然,通过chrome插件我们也可以做的到)。

相关资源:https://juejin.cn/post/6844903922021203975

 类似资料: