ajax学习笔记

1.AJAX概述

1.1AJAX简介

AJAX 全称为Asynchronous JavaScript And XML,就是异步的JS 和XML
通过AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

1.2 AJAX 的特点

1.2.1 AJAX 的优点

  1. 可以无需刷新页面而与服务器端进行通信
  2. 允许你根据用户事件来更新部分页面内容

1.2.2 AJAX 的缺点

  1. 没有浏览历史,不能回退
  2. 存在跨域问题(同源)
  3. SEO 不友好

2.HTTP相关问题

2.1 MDN 文档

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview

2.2 HTTP 请求交互的基本过程

ajax学习笔记_第1张图片

  1. 前后应用从浏览器端向服务器发送HTTP 请求(请求报文)
  2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
  3. 浏览器端接收到响应, 解析显示响应体/调用监视回调

2.3 HTTP 报文

HTTP(hypertext transport protocol)协议『超文本传输协议』,协议详细规定了浏览器和万维网服务器之间互相通信的规则。
约定, 规则

2.3.1请求报文

重点是格式与参数

行      POST  /s?ie=utf-8  HTTP/1.1 
头      Host: www.baidu.com
        Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;	
        Content-type: application/x-www-form-urlencoded
        User-Agent: chrome 83
空行
体      username=admin&password=admin

注:post请求才有请求体

Request Headers

Request Header 说明
Accept 浏览器可接收的数据格式(如:/
Accept-Language 客户端接收的语言类型(如:zh-CN,en-US)
Connection 维护客户端和服务端的连接关系(如:Keep-Alive)
Host 连接的目标主机和端口号(如:localhost:8080)
User-Agent 客户端版本号的名字
Accept-Encoding 客户端能接收的压缩数据的类型(如:gzip)
Cookie 客户端暂存服务端的信息
Content-type 发送数据的格式,get请求没有(如:application/json)

2.3.2响应报文

行      HTTP/1.1  200  OK
头      Content-Type: text/html;charset=utf-8
	   Set-Cookie: BD_CK_SAM=1;path=/
        Content-length: 2048
        Content-encoding: gzip
空行    
体      
            
            
            
                

尚硅谷

(html 文本/json 文本/js/css/图片...)

ajax学习笔记_第2张图片

  • 负载(Payload)用来查看请求发送的查询字符串和form data
  • Preview用来查看解析后的返回数据
  • Response用来查看返回数据

Response Headers

Response Headers 说明
Content-Type 服务端发送的类型及采用的编码方式(如:text/html; charset=utf-8)
Content-Encoding 服务端能够发送压缩编码类型(如:gzip)
Content-Length 服务端发送的压缩数据的长度(如:128)
Set-Cookie 服务端发送到客户端的暂存数据
Cache-Control 缓存相关
Last-Modified 缓存相关
Etag 缓存相关

2.3.3post请求体参数格式

  1. Content-Type: application/x-www-form-urlencoded;charset=utf-8
    用于键值对参数,参数的键值用=连接, 参数之间用&连接
    例如: name=%E5%B0%8F%E6%98%8E&age=12
  2. Content-Type: application/json;charset=utf-8
    用于 json 字符串参数
    例如: {“name”: “%E5%B0%8F%E6%98%8E”, “age”: 12}
  3. Content-Type: multipart/form-data
    用于文件上传请求

2.4常见的响应状态码

状态码

  • 1xx:指示信息-表示请求已接收,继续处理
  • 2xx:成功-表示请求已被成功接收
  • 3xx:重定向-要完成请求必须进行更进一步的操作
  • 4xx:客户端错误-请求有语法错误或请求无法实现
  • 5xx:服务器错误-服务器未能实现合法的请求

常见的http状态码

  • 200:客户端请求成功
  • 206:客户发送带有range头的GET请求,服务器完成了它
  • 301:重定向(永久)
  • 302:重定向(临时)
  • 304:资源未被修改,有缓存
  • 403:请求被拒绝
  • 404:资源未找到
  • 500:服务器错误
  • 504:网关超时

2.5不同类型的请求及其作用

  1. GET: 从服务器端读取数据(查)
  2. POST: 向服务器端添加新数据 (增)
  3. PUT: 更新资源 (改)
  4. DELETE: 删除服务器端数据 (删)

3. 原生AJAX 的基本使用 XHR

3.1理解

  1. 使用XMLHttpRequest (XHR)对象可以与服务器交互, 也就是发送ajax 请求
  2. 前端可以获取到数据,而无需让整个的页面刷新。
  3. 这使得Web 页面可以只更新页面的局部,而不影响用户的操作。

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的

3.2 使用步骤

const xhr = new XMLHttpRequest();
// 请求方式
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//get请求不传 body 参数,只有post请求使用
xhr.send(body) 
// 事件绑定 处理服务端返回的结果
// on  when 当....时候
// readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
//状态 0 表示未初始化  1 open方法调用完毕 2 send方法已经调用完毕 3 服务端返回部分结果 4 服务端返回了所有结果
// change  改变
xhr.onreadystatechange = function (){
     //判断 (服务端返回了所有的结果)
	if(xhr.readyState == 4 && xhr.status == 200){
		  console.log(xhr.status);//状态码
           console.log(xhr.statusText);//状态字符串
           console.log(xhr.getAllResponseHeaders());//所有响应头
           console.log(xhr.response);//响应体
	}

3.2.1get请求

      // 1. 创建对象 
      const xhr = new XMLHttpRequest();
      // 2. 初始化 设置请求方法和url
      xhr.open('GET', 'http://127.0.0.1:8000/server')
      // 3. 发送
      xhr.send();
      // 4. 事件绑定 处理服务端返回的结果
      xhr.onreadystatechange = function(){
        // readyState 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
        //判断 (服务端返回了所有的结果)
        if(xhr.readyState === 4){
          //判断响应状态码 200  404  403 401 500
          if(xhr.status >= 200 && xhr.status < 300){
            // 处理结果 行 头 空行 体
            // 响应
            console.log('状态码', xhr.status); // 状态码
            console.log('状态字符串', xhr.statusText); // 状态字符串
            console.log('所有响应头', xhr.getAllResponseHeaders()); // 所有响应头
            console.log('响应体', xhr.response); // 响应体
            //设置 result 的文本
            result.innerHTML=xhr.response;
          }
        }
      } 

GET 请求设置请求参数

设置url参数

xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');

ajax学习笔记_第3张图片

ajax学习笔记_第4张图片

3.2.2post请求

	  // 1. 创建对象
      const xhr = new XMLHttpRequest();
      // 2. 初始化 设置类型(请求方式)与url
      xhr.open('POST', 'http://127.0.0.1:8000/server');
	  //设置请求头
       xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	// 自定义头信息
	  xhr.setRequesHeader('name', 'ykyk');
      // 3. 发送   设置请求参数(请求体)
      xhr.send('a=100&b=200&c=300');
      // 4. 事件绑定
      xhr.onreadystatechange = function(){
        // 判断
        if(xhr.readyState === 4){
          if(xhr.status >=200 && xhr.status < 300){
            // 处理服务端返回的结果
            result.innerHTML = xhr.response;
          }
        }

后端设置

设置响应头允许自定义请求头 post改成all

response.setHeader('Access-Control-Allow-Header','*');

3.2.3取消发送无用的参数

有的时候有的参数是可以不填写的,这时尽管是空串也会随着请求发过去,我们可以将参数的值设置成undefined,这样就不会随请求发过去了

3.3请求超时与网络异常

// 超时设置 (2秒) 超过2s请求就取消  status 状态变成 cancel 
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function(){
	alert('网络超时,请稍后重试')
}
// 网络异常回调
xhr.onerror = function(){
	alert('网络异常,请稍后重试')
}

3.4取消请求

// 	手动取消请求		
//	network中的status中pending为等待中
//	取消就变成cancel
xhr.abort()

3.5 AJAX 请求状态

xhr.readyState 可以用来查看请求当前的状态
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState

ajax学习笔记_第5张图片

  • 0: 表示XMLHttpRequest 实例已经生成,但是open()方法还没有被调用
  • 1: 表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息
  • 2: 表示send()方法已经执行,并且头信息和状态码已经收到
  • 3: 表示正在接收服务器传来的body 部分的数据
  • 4: 表示服务器数据已经完全接收,或者本次接收已经失败了

3.6API总结

  • XMLHttpRequest():创建 XHR 对象的构造函数
  • status:响应状态码值,如 200、404
  • statusText:响应状态文本,如 ’ok‘、‘not found’
  • readyState:标识请求状态的只读属性 0-1-2-3-4
  • onreadystatechange:绑定 readyState 改变的监听
  • responseType:指定响应数据类型,如果是 ‘json’,得到响应后自动解析响应
  • response:响应体数据,类型取决于 responseType 的指定
  • timeout:指定请求超时时间,默认为 0 代表没有限制
  • ontimeout:绑定超时的监听
  • onerror:绑定请求网络错误的监听
  • open():初始化一个请求,参数为:(method, url[, async])
  • send(data):发送请求
  • abort():中断请求 (发出到返回之间)
  • getResponseHeader(name):获取指定名称的响应头值
  • getAllResponseHeaders():获取所有响应头组成的字符串
  • setRequestHeader(name, value):设置请求头

4.axios

4.1 axios 是什么?

  1. 前端最流行的 ajax请求库
  2. react/vue 官方都推荐使用 axios 发ajax 请求
  3. 文档: https://github.com/axios/axios

4.2 axios 特点

  1. 基于 xhr + promise 的异步 ajax请求库
  2. 浏览器端/node 端都可以使用
  3. 支持请求/响应拦截器
  4. 支持请求取消
  5. 请求/响应数据转换
  6. 批量发送多个请求

4.3 axios 常用语法

axios(config): 通用/最本质的发任意类型请求的方式
axios(url[, config]): 可以只指定url 发get 请求
axios.request(config): 等同于axios(config)
axios.get(url[, config]): 发get 请求
axios.delete(url[, config]): 发delete 请求
axios.post(url[, data, config]): 发post 请求
axios.put(url[, data, config]): 发put 请求

axios.defaults.xxx: 请求的默认全局配置(method\baseURL\params\timeout…)
axios.interceptors.request.use(): 添加请求拦截器
axios.interceptors.response.use(): 添加响应拦截器

axios.create([config]): 创建一个新的axios(它没有下面的功能)

axios.Cancel(): 用于创建取消请求的错误对象
axios.CancelToken(): 用于创建取消请求的 token 对象
axios.isCancel(): 是否是一个取消请求的错误
axios.all(promises): 用于批量执行多个异步请求
axios.spread(): 用来指定接收所有成功数据的回调函数的方法

ajax学习笔记_第6张图片

4.4使用

配置对象常用的配置项
{
  // 路径url
  url: '/user',

  // 请求方法,默认get
  method: 'get', 

  //基础url,最终请求的url是 baseURL+url拼接,所以再全局设置默认,可以使得发送请求时的url变得简洁
  baseURL: 'https://some-domain.com/api/',

  //设置请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  //设置请求url的query参数,可以使得url简洁。
  //比如url是https://some-domain.com/api/user  然后params如下设置,那么最终的url是:
  //https://some-domain.com/api/user?ID=12345&name=Jack
  params: {
    ID: 12345,
    name:"Jack"
  },


 //设置请求体
  data: {
    firstName: 'Fred'
  },
  
  //设置请求的另外一种格式,不过这个是直接设置字符串的
  data: 'Country=Brasil&City=Belo Horizonte',

 //请求超时,单位毫秒,默认0,不超时。
  timeout: 1000,

  //响应数据类型,默认json
  responseType: 'json', 

  //响应数据的编码规则,默认utf-8
  responseEncoding: 'utf8',

  //响应体的最大长度 
  maxContentLength: 2000,

  // 请求体的最大长度
  maxBodyLength: 2000,

  //设置响应状态码为多少时是成功,调用resolve,否则调用reject失败
  //默认是大于等于200,小于300
  validateStatus: function (status) {
    return status >= 200 && status < 300; 
  }

代码

    <button id="btn1">发送get请求button> <br><br>
    <button id="btn2">发送post请求button><br><br>
    <button id="btn3">发送put请求button><br><br>
    <button id="btn4">发送delete请求button>

    <hr>

    <div>其他发送请求的api:div><br><br>
    <button id="btn5">发送get请求1button> <br><br>
    <button id="btn6">发送post请求1button><br><br>
    <button id="btn7">发送put请求1button><br><br>
    <button id="btn8">发送delete请求1button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
<script>
    //发送get
    document.getElementById("btn1").onclick = function(){
       axios({
        method:"GET",
        url:"http://localhost:3000/posts/1"
       }).then(response=>{
           console.log(response);
       })
    };

    //发送post
    document.getElementById("btn2").onclick = function(){
       axios({
        method:"POST",
        url:"http://localhost:3000/posts",
        data:{
            title:"axios学习",
            author:"Yehaocong"
        }
       }).then(response=>{
           console.log(response);
       })
    };
    //发送put
    document.getElementById("btn3").onclick = function(){
       axios({
        method:"PUT",
        url:"http://localhost:3000/posts/2",
        data:{
            title:"axios学习",
            author:"Liaoxiaoyan"
        }
       }).then(response=>{
           console.log(response);
       })
    };
    document.getElementById("btn4").onclick = function(){
       axios({
        method:"DELETE",
        url:"http://localhost:3000/posts/2",
       }).then(response=>{
           console.log(response);
       })
    };



    //其他发送请求的api

    
    document.getElementById("btn5").onclick = function(){
        //发送get,使用get,第一个参数时url,第二个参数时config配置对象
       axios.get("http://localhost:3000/posts/1")
       .then(response=>{
           console.log(response);
       })
    };

    //发送post
    document.getElementById("btn6").onclick = function(){
        //发送post请求,第一个参数时url,第二个参数时请求体,第三个参数时config配置对象
        axios.post("http://localhost:3000/posts",
        {title:"axios学习2",
            author:"Yehaocong2"})
            .then(response=>{
           console.log(response);
       })
    };
    //发送put,
    document.getElementById("btn7").onclick = function(){
        //发送put,接收三个参数,url  请求体 、 config配置对象
       axios.put("http://localhost:3000/posts/2",{title:"axios学习",
            author:"Liaoxiaoyan"})
       .then(response=>{
           console.log(response);
       })
    };
    document.getElementById("btn8").onclick = function(){
        //发送delete请求,接收2个参数, url config配置对象
        axios.delete("http://localhost:3000/posts/3")
       .then(response=>{
           console.log(response);
       })
    };

ajax学习笔记_第7张图片

默认配置

可以设置全局默认配置,是为了避免多种重复配置在不同请求中重复,比如baseURL、timeout等,这里设置baseURL。

        axios.defaults.baseURL="http://localhost:3000";

        //因为上面配置了baseURL,所以我们之后的请求只需要配置url不用像之前那样的全路径
        axios.get("/posts/1")
       .then(response=>{
           console.log(response);
       })

4.5创建一个新的axios对象

根据指定配置创建一个新的 axios, 也就是每个新 axios 都有自己的配置
新 axios 只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
为什么要设计这个语法?
(1) 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理(比如有多个baseURL需要指定)
(2) 解决: 创建2 个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中

const instance = axios.create({ // instance是函数类型
	baseURL: 'http://localhost:3000'
})
// 使用instance发Ajax请求
instance({
	url: '/posts'
})
instance.get('/posts')

4.6拦截器

请求拦截器(在发送请求前,使用函数对请求的参数和内容进行处理和检测,若请求有问题可直接进行拦截->取消,后进先执行=则后面的请求拦截器先执行)

响应拦截器(对响应的结果预处理,先进先执行=前面的响应拦截器先执行)

1)请求拦截器:

① 在真正发送请求前执行的回调函数

② 可以对请求进行检查或配置进行特定处理

③ 失败的回调函数,传递的默认是error

④ 成功的回调函数,传递的默认是config(也必须是)

2)响应拦截器

① 在请求得到响应后执行的回调函数

② 可以对响应数据进行特定处理

③ 成功的回调函数,传递的默认是response

④ 失败的回调函数,传递的默认是error

3)请求转换器:对请求头和请求体数据进行特定处理的函数

响应转换器:将响应体json字符串解析为js对象或数组的函数

  1. 说明: 调用axios()并不是立即发送ajax 请求, 而是需要经历一个较长的流程
  2. 流程: 请求拦截器2 => 请求拦截器1 => 发ajax 请求 => 响应拦截器1 => 响应拦截器2 => 请求的回调
  3. 注意: 此流程是通过 promise 串连起来的, 请求拦截器传递的是config, 响应拦截器传递的是response

代码

script>
      //设置一个请求拦截器,在请求拦截器中可以对请求参数进行修改
      //config:配置对象
      axios.interceptors.request.use(
        function (config) {
          console.log("请求拦截器 成功 1号");
          // config.headers.test = "I am only a header!";
          //修改 config 中的参数
          config.params = { a: 100 };
          return config;
        },
        error => {
          console.log("请求拦截器 失败 1号");
          return Promise.reject(error);
        }
      );
 
      axios.interceptors.request.use(
        function (config) {
          config.timeout = 5000;
          console.log("请求拦截器 成功 2号");
          // config.headers.test = "I am only a header!";
          //修改 config 中的参数
          config.timeout = 2000;
          return config;
        },
        error => {
          console.log("请求拦截器 失败 2号");
          return Promise.reject(error);
        }
      );
 
      //设置一个响应拦截器,可以对响应结果做一些处理
      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 1号");
            //返回到请求回调时,只要data数据
             return response.data;
        },
        function (error) {
          console.log("响应拦截器 失败 1号");
          return Promise.reject(error);
        }
      );
 
      //设置一个响应拦截器
      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 2号");
          return response;
        },
        function (error) {
          console.log("响应拦截器 失败 2号");
          return Promise.reject(error);
        }
      );
 
      //发送请求
      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
      })
        .then((response) => {
          console.log("自定义回调处理成功的结果");
          //console.log(response);
        })
        .catch((reason) => {
          console.log(reason);
        });
    </script>

ajax学习笔记_第8张图片

4.7取消请求

0.22版本之前可以使用,0.22开始被废弃

  <body>
    <div class="container">
      <h1 class="page-header">axios取消请求</h1>
      <button class="btn btn-primary">发送请求</button>
      <button class="btn btn-warning">取消请求</button>
    </div>
  </body>
  <script>
    //获取按钮
    const btns = document.querySelectorAll("button");
    //2.声明一个全局变量
    let cancel = null;
    //发送请求
    btns[0].onclick = () => {
      //检测上一次请求是否已经完成
      if (cancel !== null) {
        //则代表上一次请求还未取消,故直接取消上一次请求
        cancel();
      }
      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
        //1.添加配置对象的属性
        cancelToken: new axios.CancelToken((c) => {
          //3.将c的值赋值给cancel
          cancel = c;
        }),
      }).then((response) => {
        console.log(response);
        //当请求执行完后 将cancel进行初始化设置
        cancel = null;
      });
    };
 
    //取消请求
    btns[1].onclick = () => {
      cancel();
    };
  </script>

0.22新方法

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
 let btn = document.querySelectorAll('button');
const controller = new AbortController();
      btn[0].onclick = function () {
          axios( {
              url:'https://api.uomg.com/api/get.kg?songurl=https://node.kg.qq.com/play?s=YaCv8EYfJunVWYcH',
              signal: controller.signal
              }).then(function(response) {
                  console.log(response);
              });
      }

      btn[1].onclick = function () {
        controller.abort()
      }

4.8在vue中封装axios

requests.js

//对于axios进行二次封装
import axios from 'axios';
//获取仓库:存储数据
import store from '@/store';

//axios.create方法执行,其实返回一个axios和request一样的
let requests = axios.create({
  //基础路径,发请求URL携带api【发现:真实服务器接口都携带/api】
  baseURL: '/api',
  //超时的设置
  timeout: 5000,
});

//请求拦截器:将来项目中【N个请求】,只要发请求,会触发请求拦截器!!!
requests.interceptors.request.use(config => {
  //请求拦截器:请求头【header】,请求头能否给服务器携带参数
  //请求拦截器:其实项目中还有一个重要的作用,给服务器携带请求们的公共的参数
  if (store.state.detail.nanoid_token) config.headers.userTempId = store.state.detail.nanoid_token;
  if (store.state.user.token) config.headers.token = store.state.user.token;

  return config;
});

//响应拦截器:请求数据返回会执行
requests.interceptors.response.use(
  res => {
    //res:实质就是项目中发请求、服务器返回的数据
    return res.data;
  },
  err => {
    //温馨提示:某一天发请求,请求失败,请求失败的信息打印出来
    alert(err.message);
    //终止Promise链
    return new Promise();
  }
);

//最后需要暴露:暴露的是添加新的功能的axios,即为requests
export default requests;

使用

import requests from '@/api/requests';
//注册的接口
export const reqRegister = data =>
  requests({ url: `/user/passport/register`, method: 'post', data });

5.fetch

5.1XMLHttpRequest缺点

浏览器提供了原生的AJAX实现类XMLHttpRequest,基于该类实例,我们可以实现在网页上发送AJAX请求到服务端。

但是XMLHttpRequest的设计并不完美,主要体现在以下几个方面:

HTTP请求,响应都被耦合在XMLHttpRequest实例上,结构不够简单明了
采用事件回调的方式获取HTTP响应,可能会产生回调地狱
如果HTTP响应数据过大,则会占用大量内存
最后一点就是,XMLHttpRequest实现AJAX的步骤太零碎了

5.2fetch的优点

fetch和XMLHttpRequest一样,也是浏览器原生的,用于发送AJAX请求。

fetch

ajax学习笔记_第9张图片

XMLHttpRequest之后诞生的,它旨在解决XMLHttpRequest的不足,所以XMLHttpRequest的缺点就是它的优点,具体优点如下

  • 语法简单,结构清晰明了
  • 支持Promise获取异步的HTTP响应
  • HTTP响应支持流式获取,内存友好

fetch被设计为函数,通过fetch函数调用即可发起AJAX,而不需要像XMLHttpRequest那样创建实例,然后基于xhr实例发起AJAX。

fetch('http://localhost:3000/test') // fetch函数调用即发起AJAX

fetch函数返回一个Promise对象,而Promise对象的结果值就是HTTP响应

fetch('http://localhost:3000/test').then(response => { // fetch函数返回值是一个Promise类型对象
    console.log(response) // 该Promise对象的结果值response就是HTTP响应

fetch函数返回的Promise对象的结果值HTTP响应是流式获取,即使HTTP响应数据很大,也不会占用过多的内存。

5.3fetch的请求和响应

5.3.1Request

fetch(url,options).then((response)=>{
//处理http响应
},(error)=>{
//处理错误
})

url :是发送网络请求的地址。

options:发送请求参数,

  • body - http请求参数
  • mode - 请求的模式
    • cors:默认值,允许跨域请求。
    • same-origin:只允许同源请求。
    • no-cors:请求方法只限于 GET、POST 和 HEAD,并且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求。
  • cache - 用户指定缓存。
  • method - 请求方法,默认GET
  • signal - 用于取消 fetch
  • headers - http请求头设置
  • keepalive - 用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
  • credentials -是否发送 Cookie
    • same-origin:默认值,同源请求时发送 Cookie,跨域请求时不发送。
    • include:不管同源请求,还是跨域请求,一律发送 Cookie。
    • omit:一律不发送。
  • referrer- 用于设定fetch()请求的referer标头
  • referrerPolicy- 用于设定Referer标头的规则
    • no-referrer-when-downgrade:默认值,总是发送Referer标头,除非从 HTTPS 页面请求 HTTP 资源时不发送。
    • no-referrer:不发送Referer标头。
    • origin:Referer标头只包含域名,不包含完整的路径。
    • origin-when-cross-origin:同源请求Referer标头包含完整的路径,跨域请求只包含域名。
    • same-origin:跨域请求不发送Referer,同源请求发送。
    • strict-origin:Referer标头只包含域名,HTTPS 页面请求 HTTP 资源时不发送Referer标头。
    • strict-origin-when-cross-origin:同源请求时Referer标头包含完整路径,跨域请求时只包含域名,
    • HTTPS 页面请求 HTTP 资源时不发送该标头。
    • unsafe-url:不管什么情况,总是发送Referer标头。
fetch('http://localhost:3000/test',{
    method: 'post',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        name: 'qfc',
        age: 18
    })
}).then(res => {
    console.log(res)
})

ajax学习笔记_第10张图片

其中需要注意的是Request对象的body属性,该属性值支持

  • 查询参数字符串,如’name=qfc&age=18’
  • 文本字符串,如’{“name”:“qfc”, “age”: 18}’
  • FormData对象
  • Blob对象
  • ReadableStream对象
  • BufferSource对象

5.3.2Response

fetch 请求成功后,响应 response 对象如图:

ajax学习笔记_第11张图片

  • status - http状态码,范围在100-599之间

  • statusText - 服务器返回状态文字描述

  • ok - 返回布尔值,如果状态码2开头的,则true,反之false

  • headers - 响应头

  • body - 响应体。响应体内的数据,根据类型各自处理。

  • type - 返回请求类型。

    • basic: 标准值, 同源响应, 带有所有的头部信息除了“Set-Cookie” 和 “Set-Cookie2″.

    • cors: Response 接收到一个有效的跨域请求.

    • error: 网络错误. 没有有用的描述错误的信息。响应的状态为0,header为空且不可变。从 Response.error()中获得的响应的类型.

    • opaque: 响应 “no-cors” 的跨域请求.

    • redirected - 返回布尔值,表示该 Response 是否来自一个重定向,如果是的话,它的 URL 列表将会有多个条目。

  • url:HTTP请求URL

其中,我们需要注意的是body属性值是一个可读流,所以我们无法直接获取body内容,需要从可读流中读取内容,而读取可读流中内容也是一个异步操作,Response贴心的为我们提供了如下实例方法去异步地获取body可读流中的内容

  • json() 读取body内容为JSON对象
  • text() 读取body内容为普通文本字符串
  • formData() 读取body内容为FormData对象
  • blob() 读取body内容为Blob对象
  • arrayBuffer() 读取body内容为ArrayBuffer对象

以上方法都返回一个Promise对象,且Promise对象的结果值为它们读取到并转换为对应格式的数据。

            fetch('http://127.0.0.1:8000/fetch-server?vip=10', {
                //请求方法
                method: 'POST',
                //请求头
                headers: {
                    name:'atguigu'
                },
                //请求体
                body: 'username=admin&password=admin'
            }).then(response => {
                // return response.text();
                return response.json();
            }).then(response=>{
                console.log(response);
            });

通过以上代码测试发现,当response.json()返回的Promise的结果值确实是body实际内容,并且自动被转化为JSON对象。

5.4GET和POST

5.4.1GET

  fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`,{
   method:'GET'
  }).then(response=>{
   console.log('响应',response)
  })

5.4.2POST

fetch(`http://localhost:80/fetch`,{
 method:'POST',
 headers:{
  'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
 },
 body:`user=${user.value}&pas=${pas.value}`
 }).then(response=>{
  console.log('响应',response)
})

如果是提交json数据时,需要把json转换成字符串。如

fetch(`http://localhost:80/fetch`,{
 method:'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        name: 'qfc',
        age: 18
    }).then(response=>{
  console.log('响应',response)
})

如果提交的是表单数据,使用 formData转化下,如:

body:new FormData(form)

上传文件,可以包含在整个表单里一起提交,如:

const input = document.querySelector('input[type="file"]');

const data = new FormData();
data.append('file', input.files[0]);
data.append('user', 'foo');

fetch('/avatars', {
  method: 'POST',
  body: data
});

5.5fetch默认不带cookie

传递cookie时,必须在header参数内加上 credentials:‘include’,才会像 xhr 将当前cookie 带有请求中。

5.6异常处理

fetch 不同于 xhr ,xhr 自带取消、错误等方法,所以服务器返回 4xx 或 5xx 时,是不会抛出错误的,需要手动处理,通过 response 中的 status 字段来判断。

6.跨域

6.1 同源策略

  • 同源策略(Same-Origin Policy)最早由Netscape 公司提出,是浏览器的一种安全策略
  • 同源: 协议、域名、端口号必须完全相同
  • 跨域: 违背同源策略就是跨域

6.2 如何解决跨域

6.2.1JSONP

jsonp 只支持get请求不支持post请求

1) JSONP 是什么

JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明
才智开发出来,只支持get 请求。

2) JSONP 怎么工作的?

在网页有一些标签天生具有跨域能力,比如:img link iframe script。
JSONP 就是利用script 标签的跨域能力来发送请求的。

3) JSONP 的使用

html代码

            //1. 创建 script 标签
            const script = document.createElement('script');
            //2. 设置标签的 src 属性
            script.src = 'http://127.0.0.1:8000/check-username?callback=abc';
            //3. 将script 添加到body 中
            document.body.appendChild(script);
            function abc(data) {
                alert(data.name);
            };

后端代码

app.get("/check-username" , function (req , res) {
	var callback = req.query.callback;
    const data = {
        name: '孙悟空'
    };
    //将数据转化为字符串
    let str = JSON.stringify(data);
    //返回结果(一段可执行的JavaScript代码)
    response.end(`handle(${str})`);
});

6.2.2 CORS

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

  1. CORS 是什么?
    CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方
    案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持
    get 和post 请求。跨域资源共享标准新增了一组HTTP 首部字段,允许服务器声明哪些
    源站通过浏览器有权限访问哪些资源

  2. CORS 怎么工作的?
    CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应
    以后就会对响应放行。

  3. CORS 的使用
    主要是服务器端的设置:

router.get("/testAJAX" , function (req , res) {
	//通过res 来设置响应头,来允许跨域请求
	//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
	res.set("Access-Control-Allow-Origin","*");//允许所有来源访问
	res.send("testAJAX 返回的响应");
});

你可能感兴趣的:(ajax学习笔记,ajax,学习,前端,javascript)