【学习笔记】尚硅谷-AJAX

Ajax简介

Asynchronous JavaScript And XML:在不网页无刷新跳转的情况下,向服务器(后端)发送HTTP请求并得到HTTP响应

Ajax就是一个异步无刷新请求,无需更新整个页面就异步加载一些数据,交互性更强。

Ajax优缺点

  1. 无需刷新页面即可与服务器端进行通信。
  2. 允许根据用户事件来更新部分页面内容。
  1. 无浏览历史,不能回退。
  2. 存在跨域问题(同源):如a.comb.com发送AJAX请求默认是不可行的。
  3. SEO(Search Engine Optimization)不友好。

如何使用Ajax?

  • 原生
  • JQuery
  • fetch函数
  • axios工具包

XML简介

可扩展标记语言(eXtensible Markup Language)。

与HTML的区别?

XML 被设计用来传输和存储数据,其焦点是数据的内容;HTML 被设计用来显示数据,其焦点是数据的外观。

(1)可扩展性方面:HTML不允许用户自行定义他们自己的标识或属性,而在XML中,用户能够根据需要自行定义新的标识及属性名,以便更好地从语义上修饰数据。

(2)结构性方面:HTML不支持深层的结构描述,XML的文件结构嵌套可以复杂到任意程度,能表示面向对象的等级层次。

(3)可校验性方面:HTML没有提供规范文件以支持应用软件对HTML文件进行结构校验,而XML文件可以包括一个语法描述,使应用程序可以对此文件进行结构校验。

AJAX的数据传输格式现在已经逐渐被JSON取代

HTTP相关问题

MDN 文档

HTTP 请求交互的基本过程
  1. 应用从浏览器端向服务器发送HTTP请求(请求报文)
  2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
  3. 浏览器端接收到响应, 解析显示响应体/调用监视回调
  • HTTP请求报文
请求行    method URL 协议版本
如:POST /s?ie=utf-8 HTTP/1.1
---
请求头
Host: baidu.com
Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
Content-Type: application/x-www-form-urlencoded # 或者application/json
User-Agent: chrome ...
...
---
请求体
username=tom&pwd=123 # or {"username": "tom", "pwd": 123}
  • HTTP响应报文
响应状态行    status statusText
如:200 OK
---
响应头
Content-Type: text/html?charset=utf-8
Content-Length: 2048
Content-encoding: gzip
...
响应体
# HTML代码/json文本/js/css/图片
  • POST请求体参数格式
Content-Type: application/x-www-form-urlencoded;charset=utf-8
# 用于键值对参数,参数的键值使用“=”连接,参数之间使用“&”连接
如:name=小小&age=11
---
Content-Type: application/json;charset=utf-8
# 用于json字符串参数
如:{"name": "小小","age":11}
---
Content-Type: multipart/form-data
# 用于文件上传请求

常见的响应状态码

200 OK 请求成功。一般用于GET 与POST 请求
201 Created 已创建。成功请求并创建了新的资源
401 Unauthorized 未授权/请求要求用户的身份认证
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求

不同类型的请求及其作用

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

API 的分类

  1. REST API: restful (Representational State Transfer (资源)表现层状态转化)

    (1) 发送请求进行CRUD 哪个操作由请求方式来决定
    (2) 同一个请求路径可以进行多个操作
    (3) 请求方式会用到GET/POST/PUT/DELETE

  2. 非REST API: restless

    (1) 请求方式不决定请求的CRUD 操作
    (2) 一个请求路径只对应一个操作
    (3) 一般只有GET/POST

http请求与ajax请求的区别

  1. ajax请求是一种特别的 http请求
  2. 对服务器端来说,,没有任何区别, 区别在浏览器端
  3. 浏览器端发请求:只有XHRfetch 发出的才是ajax 请求,其它所有的都是非ajax 请求
  4. 浏览器端接收到响应
    (1) 一般请求:浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面
    (2) ajax请求:浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数传入响应相关数据

原生AJAX:使用 XHR

XHR(XMLHttpRequest)用于与服务器交互数据,是AJAX功能实现所依赖的对象,JQuery中的AJAX就是对XHR的封装。

XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。

XHR接口强制要求每个请求都具备严格的HTTP语义–应用提供数据和URL,浏览器格式化请求并管理每个连接的完整生命周期,所以XHR仅仅允许应用自定义一些HTTP首部,但更多的首部是不能自己设定的,如:

Accept-Charset, Accept-Encoding, Access-Control-* Host, Upgrade, Connection, Referer, Origin Cookie, Sec-, Proxy-, 及其他首部

准备工作

个人觉得 node.js(执行.js文件的JavaScript代码)和 npm 有些类似 python 解释器和 pip 包管理工具的关系。

  • 安装node.js

    Node.js发布于2009年5月,是一个基于Chrome V8引擎的JavaScript【事件驱动脚本语言】运行环境,使用了一个事件驱动、非阻塞式I/O模型, 让JavaScript 运行在服务端的开发平台。

    简单的说 Node.js 就是运行在服务端的 JavaScript

    Node可以在不新增额外线程的情况下,依然可以对任务进行并发处理 —— Node.js是单线程的。它通过事件循环(event loop)来实现并发操作,对此,我们应该要充分利用这一点 —— 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。

    安装地址:http://nodejs.cn/

  • 第一个程序

    Node.js 应用组成部分:

    1. 引入 required 模块:使用 require 指令来载入 Node.js 模块。
    2. 创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
    3. 接收请求与响应请求 :服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。

    在项目的根目录下创建一个叫 server.js 的文件,写入以下代码:

    var http = require('http');
    
    http.createServer(function (request, response) {
    
        // 发送 HTTP 头部 
        // HTTP 状态值: 200 : OK
        // 内容类型: text/plain
        response.writeHead(200, {'Content-Type': 'text/plain'});
    
        // 发送响应数据 "Hello World"
        response.send('Hello World\n');
    }).listen(8888);
    
    // 终端打印如下信息
    console.log('Server running at http://127.0.0.1:8888/');
    

    以上代码我们完成了一个可以工作的 HTTP 服务器。使用 node 命令执行以上的代码:

    node server.js
    ## Server running at http://127.0.0.1:8888/
    
  • NPM

    NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:

    • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
    • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
    • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

    由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 “npm -v” 来测试是否成功安装。

  • 安装express(web框架模块)

    Express中文网:https://www.expressjs.com.cn/

    nodeJS相关和npm使用参考:https://www.runoob.com/nodejs/nodejs-npm.html

    1. 初始化环境(在项目根目录下)
    npm init --yes
    
    1. 安装express模块(项目路径下)
    npm install express --save
    npm install express -g --save  # 全局
    
    1. 编写js代码
    // 1. 引入express
    const express = require('express');
    
    // 2. 创建应用对象
    const app = express();
    
    // 3. 创建路由规则
    // request 是对请求报文的封装
    // response 是对响应报文的封装
    app.get('/', (request, response) => {
      //  设置响应
      response.send("Hello Express");
    });
    
    // 4. 监听端口,启动服务
    app.listen(8000, () => {
      console.log("server is running on http://127.0.0.1:8000/");
     })
    
    1. 运行程序
  • 安装nodemon自动重启工具

    文件内容有修改自动重新启动服务:https://www.npmjs.com/package/nodemon

    安装

    npm install -g nodemon
    

    启动服务

    ndoemon server.js
    

注意点

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

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

核心对象使用步骤

  • 创建XMLHttpRequest 对象

    var xhr = new XMLHttpRequest();
    
  • 设置请求信息(请求方法和url)

    // 请求方式
    xhr.open(method, url);
    //可以设置请求头,一般不设置
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    
    // 自定义请求头
    xhr.setRequestHeader('name', 'moonjay');
    // 自定义请求头需要在server.js加入 response.setHeader('Access-Control-Allow-Headers', '*');
    
  • 发送请求

    xhr.send(body) //get请求不传 body 参数,只有post请求使用
    
  • 接收响应(事件绑定,处理服务端返回的结果)

    //xhr.responseXML 接收 xml格式 的响应数据
    //xhr.responseText 接收 文本格式 的响应数据
    xhr.onreadystatechange = function(){
    	// readyState 是 xhr对象中的属性, 表示状态 0 1 2 3 4
    	if(xhr.readyState == 4 && xhr.status == 200){
    		var text = xhr.responseText;
    		console.log(text);
    	}
    }
    

AJAX 请求状态

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

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

示例

  • GET 请求(点击返回响应信息)

    文件结构(浏览器端–html文件;服务器端–js文件)

    server.js

    // 1. 引入express
    const express = require('express');
    
    // 2. 创建应用对象
    const app = express();
    
    // 3. 创建路由规则
    app.get('/server', (request, response) => {
      // 设置响应头 设置允许跨域
      response.setHeader('Access-Control-Allow-Origin', '*');
      // 设置响应体
      response.send("Hello Ajax");
    });
    
    // 4. 监听服务
    app.listen(8000, () => {
      console.log("server is running on http://127.0.0.1:8000/");
     })
    

    01Get.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Ajax GET 请求</title>
      <style>
        #result {
          width: 200px;
          height: 100px;
          border: solid 1px #90b;
        }
      </style>
    </head>
    <body>
      <button>点击发送请求</button>
      <div id="result"></div>
      <script>
        //获取button元素
        const btn = document.getElementsByTagName('button')[0];
        const result = document.getElementById('result');
        //绑定事件
        btn.onclick = function(){
          // 1. 创建对象 
          const xhr = new XMLHttpRequest();
          // 2. 初始化 设置请求方法和url
          xhr.open('GET', 'http://127.0.0.1:8000/server')
          // 3. 发送, GET不发送body POST发送
          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;
              }else{
              }
            }
          } 
        }
      </script>
    </body>
    </html>
    

    GET 请求设置请求参数

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

    可以在Headers中看到Query String Parameters多出三个参数

  • POST请求(鼠标放到div中,发post请求,将响应体放在div中呈现)

    server.js添加POST

    app.post('/server', (request, response) => {
      // 设置响应头, 设置允许跨域
      response.setHeader('Access-Control-Allow-Origin', '*');
      // 设置响应体
      response.send("Hello Ajax POST");
    });
    

    01Post.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Ajax POST 请求</title>
      <style>
        #result {
          width: 200px;
          height: 100px;
          border: solid 1px #903;
        }
      </style>
    </head>
    <body>
      <div id="result"></div>
      <script>
        // 获取元素对象
        const result = document.getElementById('result');
        // 绑定事件
        result.addEventListener("mouseover", function(){
          // 1. 创建对象
          const xhr = new XMLHttpRequest();
          // 2. 初始化 设置类型(请求方式)与url
          xhr.open('POST', 'http://127.0.0.1:8000/server');
          // 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;
              }
            }
          }
        });
      </script>
    </body>
    </html>
    

JSON数据请求

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

// app.all() -- 可以get、post
app.all('/json-server', (request, response) => {
  // 设置响应头, 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*');
  // 设置响应头, 设置允许自定义头信息
  response.setHeader('Access-Control-Allow-Headers', '*');
  // 响应一个数据
  const data = {
    name: 'moonjay'
  };
  // 对 对象 进行 字符串 转换
  let str = JSON.stringify(data)
  // 设置响应体 
  response.send(str);
});

01JSON.html:(按下键盘任意按键触发)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JSON</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #89b;
    }
  </style>
</head>
<body>
  <div id="result"></div>
  <script>
    const result = document.getElementById('result');
    // 绑定键盘按下事件
    window.onkeydown = function(){
      // 发送请求
      const xhr = new XMLHttpRequest();
      // *2*.(自动转换) 设置响应体数据的类型(自动转换)
      xhr.responseType = 'json';
      // 初始化
      xhr.open('GET', 'http://127.0.0.1:8000/json-server');
      // 发送
      xhr.send();
      // 事件绑定
      xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
          if(xhr.status >= 200 && xhr.status < 300){
            console.log(xhr.response);
            // 1. 手动对数据转化 (字符串再转换成json)
            // let data = JSON.parse(xhr.response); //转换成json
            // result.innerHTML = data.name;
            // 2. 自动转换
            result.innerHTML = xhr.response.name; //已经自动变成json
          }
        }
      }
    }
  </script>
</body>
</html>

请求超时与网络异常

// 超时设置 (2秒)
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function(){
	alert('网络超时,请稍后重试')
}
// 网络异常回调   在chrome’检查‘的Network选项卡可以设置网络环境--设为offline
xhr.onerror = function(){
	alert('网络异常,请稍后重试')
}
// 手动取消请求
xhr.abort()

server.js中设置:

app.get('/delay', (request, response) =>{
     response.setHeader('Access-Control-Allow-Origin', '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 3000)
});

重复请求问题

用户可能重复向服务器发送相同请求,造成服务器端响应压力,如何解决?

创建一个只有一个按钮的html网页,html代码略,下为script脚本:

const btn = document.querySelector('button')
let x = null;
// 标识变量 是否正在发送AJAX请求
let isSending = false;
btn.onclick = function(){
    // 判断标识变量,如果正在发送,则取消该请求创建一个新的请求
    if(isSending) x.abort();
    x = new XMLHttpRequest();
    // 修改标识变量的值
    isSending = true;
    x.open("GET", "http://127.0.0.1:8000/delay");
    x.send();
    x.onreadystatechange = function(){
        if(x.readyState === 4){
            //修改标识变量
            isSending = false;
        }
    }
}

IE 缓存问题

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

解决方式:浏览器的缓存是根据url 地址来记录的,所以我们只需要修改url 地址即可避免缓存问题。

xhr.open("get","/testAJAX?t="+Date.now());

API总结

  • 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):设置请求头

JQuery中的AJAX

get 请求

$.get(url, [data], [callback], [type])

post 请求

$.post(url, [data], [callback], [type])
  • url:请求的URL 地址
  • data:请求携带的参数
  • callback:载入成功时回调函数
  • type:设置返回内容格式,xml, html, script, json, text, _default

通用方法

$.ajax({
	// url
	url: 'http://127.0.0.1:8000/jquery-server',
	// 参数
	data: {a:100, b:200},
	// 请求类型
	type: 'GET',
	// 响应体结果
	dataType: 'json',
	// 成功的回调
	success: function(data){console.log(data);},
	// 超时时间
	timeout: 2000,
	// 失败的回调
	error: function(){console.log('出错la~');},
	// 头信息
	headers: {
		c: 300,
		d: 400
	}	
})

示例

JQuery_AJAX.html

<!DOCTYPE html>
<html lang="en">
    <head>
		<meta charset="UTF-8">
		<title>JQuery发送Ajax请求</title>
        <!--crossorigin="anonymous"是跨域匿名请求的意思,向css或js文件发送请求时不会携带当前站点的cookies-->
        <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
        <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
	</head>
    <body>
        <div class="container">
            <h2 class="page-header">JQuery发送Ajax请求</h2>
            <button class="btn btn-primary">GET</button>
            <button class="btn btn-danger">POST</button>
            <button class="btn btn-info">通用型方法Ajax</button>
        </div>
    </body>
    <script>
        $('button').eq(0).click(function(){
            $.get('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
                console.log(data)
            }, 'json');  //响应体类型为json
        })

        $('button').eq(1).click(function(){
            $.post('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
                console.log(data)
            }); //响应体类型为字符串
        })

        $('button').eq(2).click(function(){
            $.ajax({
                // url
                url: 'http://127.0.0.1:8000/jquery-server',
                // 参数
                data: {a:100, b:200},
                // 请求类型
                type: 'GET',
                // 响应体结果--可选,默认为字符串
                dataType: 'json',
                // 成功的回调
                success: function(data){console.log(data);},
                // 超时时间
                timeout: 2000,
                // 失败的回调
                error: function(){console.log('出错la~');},
                // 头信息
                headers: {
                    c: 300,
                    d: 400
                }
            });
        })
    </script>
</html>

server.js加入以下代码:

// JQuery_AJAX.html文件用  all--可以响应get和post
app.all('/jquery-server', (request, response) => {
  // 设置响应头
  response.setHeader('Access-Control-Allow-Origin', '*');

  // 设置响应头, 设置允许自定义头信息,
  // 第3个按钮有头信息参数,不设置会出错
  response.setHeader('Access-Control-Allow-Headers', '*');

  // response.send("hello JQuery AJAX");

  // 响应体类型为json
  const data = {name: "moonjay"};
  response.send(JSON.stringify(data))
});

axios发送AJAX请求

axios的Github链接:https://github.com/axios/axios

是一个基于promise的网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在客户端 (浏览端) 则使用XMLHttpRequest。

axios本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范

主要特点

  • 从浏览器创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF
  • 🆕 Automatic data object serialization to multipart/form-data and x-www-form-urlencoded body encodings

使用npm安装

npm install axios

HTML页面引用CDN链接

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!--or-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

GET、POST、通用方法

参考链接:https://github.com/axios/axios#request-method-aliases

axios.get(url[, config])
axios.post(url[, data[, config]])
axios()

示例

server.js文件加入以下代码:

// axios_ajax.html文件用
app.all('/axios-server', (request, response) => {
  // 设置响应头
  response.setHeader('Access-Control-Allow-Origin', '*');

  // 设置响应头, 设置允许自定义头信息,
  // 第3个按钮有头信息参数,不设置会出错
  response.setHeader('Access-Control-Allow-Headers', '*');

  // response.send("hello axios AJAX");

  // 响应体类型为json
  const data = {name: "moonjay axios"};
  response.send(JSON.stringify(data))
});

axios_Ajax.html

<!DOCTYPE html>
<html lang="en">
    <head>
		<meta charset="UTF-8">
		<title>axios发送Ajax请求</title>
        <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
        <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js"></script>
	</head>
    <body>
        <div class="container">
            <h2 class="page-header">axios发送Ajax请求</h2>
            <button class="btn btn-primary">GET</button>
            <button class="btn btn-danger">POST</button>
            <button class="btn btn-info">Ajax</button>
        </div>
    </body>
    <script>
        const btns = document.querySelectorAll('button');

        //配置 baseURL
        axios.defaults.baseURL = 'http:127.0.0.1:8000'

        btns[0].onclick = function(){
            //GET请求
            axios.get("/axios-server", {
                // url参数
                params:{
                    id: 100,
                    vip: 7
                },
                //请求头信息
                headers:{
                    name: "moonjay",
                    age: 20
                }
            }).then(value => {
                console.log(value);
            });
        }

        btns[1].onclick = function(){
            //POST请求
            axios.post("/axios-server",
            // 请求体 第2个参数
            {
                username: "admin",
                pwd: 123456
            },
            {
                // url参数
                params:{
                    id: 101,
                    vip: 8
                },
                //请求头信息
                headers:{
                    h: 416,
                    w: 416,
                    c: 3
                }
            }).then(value => {
                console.log(value);
            });
        }

        btns[2].onclick = function(){
            // 通用方式
            axios({
                //请求方法
                method: "POST",
                //url
                url: '/axios-server',
                // url参数
                params:{
                    vip: 1,
                    level: 30
                },
                //头信息
                headers:{
                    a:100,
                    b:200
                },
                //请求体参数
                data:{
                    user:"m_ad",
                    pwd:123
                }
            }).then(response => {
                console.log(response);
            })
        }
    </script>
</html>

fetch()

参考链接:WindowOrWorkerGlobalScope接口方法:fetch()

创建只有一个按钮的html网页包含如下script脚本:

const btn = document.querySelector('button')

btn.onclick = function(){
   fetch('http:127.0.0.1:8000/fetch-server', {
       //请求方法
       method:"POST",
       //请求头
       headers:{
           name:"moonjay",
           age:23
       },
       //请求体
       body: 'username=admin&pwd=123'
   }).then(response => {
       console.log(response);
       // or return response.json();
   }) // 返回类型为 promise
}

server.js文件修改同上

跨域

Ajax默认遵守同源策略

首先介绍一下同源与跨域:

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

如何解决跨域

  • JSONP
  • CORS

JSONP

什么是JSONP

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

为什么我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )呢?这是因为同源策略。

由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

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

原理展示

新建HTML页面JSONP_Ajax.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>JSONP原理</title>
    </head>
    <body>
        <script src="./js/app.js"></script>
    </body>
</html>

同级目录下,新建js/app.js

const data = {
    name: "moonjay"
};

console.log(data)

运行程序,访问HTML页面(直接打开.html文件,使用的是file协议)即可在控制台看到输出。

借助VS Code的插件–Live Server打开.html文件,使用的是HTTP协议,访问的是127.0.0.1:port/HTML文件路径。此时,<script src="127.0.0.1:port/js文件路径"></script>

JSONP的使用

JSONP_Ajax.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>JSONP原理</title>
		<style>
			#result{
				width: 300px;
				height: 100px;
				border: solid 1px #78a;
			}
		</style>
	</head>
	<body>
		<div id="result"></div>

		用户名:<input type="text" id="username">
		<p></p>

		<script>
			const result = document.getElementById('result');
			const input = document.querySelector('input');
			const p = document.querySelector('p');

			// 声明 handle 函数
			function handle1(data){
				// div填充
				result.innerHTML = data.name;
			}

			function handle2(data){
				// 输入框 和 p标签文本
				input.style.border = "solid 1px #f00";
				p.innerHTML = data.msg;
			}

			//绑定事件
			input.onblur = function(){
				//获取用户输入值
				let username = this.value;
				// 1.创建 script 标签
				const script = document.createElement('script');
				// 2.设置标签的 src
				script.src = 'http://127.0.0.1:8000/check_username'
				// 3.将 script标签插入文档中
				document.body.appendChild(script);
			}
		</script>
		
		<!--script脚本链接放最后 不然出现handle未定义-->
		<!-- <script src="./js/app.js"></script> -->
		<script src="http://127.0.0.1:8000/jsonp-server"></script>
</body>
</html>

server.js中加入代码:

// jsonp_ajax.html文件用 -- 1
app.all('/jsonp-server', (request, response) => {
  // response.send("console.log('hello jsonp')"); //传递脚本

  const data = {
    name: "moonjay jsonp",
  };
  let str = JSON.stringify(data);
  response.send(`handle1(${str})`);
});

// jsonp_ajax.html文件用 -- 2
app.all('/check_username', (request, response) => {
  const data = {
    exist: 1,
    msg: '用户名已存在'
  };
  let str = JSON.stringify(data);
  response.send(`handle2(${str})`);
});

jQuery中的JSONP

参数 callback 是固定写法
server.js

控制台查看callback参数:

HTML文档:

CORS

文档链接:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

CORS 是什么?

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

CORS 怎么工作的?

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

CORS 的使用

主要是服务器端的设置:

router.get("/testAJAX" , function (req , res) {
	//通过res 来设置响应头,来允许跨域请求,不然会报CORS错误
	//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
	res.set("Access-Control-Allow-Origin","*");
	res.send("testAJAX 返回的响应");
});
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值