【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)

文章目录

    • 1 Ajax 概述
      • 1.1 AJAX 简介
      • 1.2 XML 简介
      • 1.3 AJAX 的特点
        • 1.3.1 AJAX 的优点
        • 1.3.2 AJAX 的缺点
      • 1.4 AJAX 属性和方法
    • 2. HTTP相关问题
      • 2.1 MDN 文档
      • 2.2 HTTP 请求交互的基本过程
      • 2.3 HTTP 请求报文
      • 2.4 HTTP 响应报文
      • 2.5 post 请求体参数格式
      • 2.6 响应状态码
      • 2.7 不同类型的请求及其作用
      • 2.8 API 的分类
      • 2.9 区别:一般 http 请求与 ajax 请求
    • 3 原生 AJAX 的基本使用 XHR
      • 3.0 准备工作
        • 3.0.1 安装 node.js
        • 3.0.2 安装 express(服务端框架)
        • 3.0.3 安装 nodemon 自动重启工具
      • 3.1 理解
      • 3.2 核心对象使用步骤
        • 3.2.1 创建 XMLHttpRequest 对象
        • 3.2.2 设置请求信息(请求方法和url)
        • 3.2.3 发送请求
        • 3.2.4 接收响应(事件绑定,处理服务端返回的结果)
      • 3.3 GET 请求
      • 3.4 POST 请求
      • 3.5 设置请求头信息
      • 3.6 JSON 数据请求
      • 3.7 IE 缓存问题
      • 3.8 请求超时与网络异常
      • 3.9 取消请求
      • 3.10 请求重复发送问题
    • 4 jQuery 发送请求
      • 4.1 get 请求
      • 4.2 post 请求
    • 5 Axios 发送请求
    • 6 fetch 发送请求
    • 7 跨域
      • 7.1 同源策略
      • 7.2 JSONP
        • 7.2.1 原理
        • 7.2.2 JSONP 实践
        • 7.2.3 jQuery 中的 JSONP
      • 7.3 CORS
    • 8 完整的 server.js 代码

PS:服务器端完整代码 server.js 附在文章末尾
学习视频地址:https://www.bilibili.com/video/BV1WC4y1b78y?p=1

1 Ajax 概述

1.1 AJAX 简介

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

1.2 XML 简介

  • XML 可扩展标记语言
  • XML 被设计用来传输和存储数据
  • XMLHTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据

比如说我有一个学生数据:

​ name = “孙悟空” ; age = 18 ; gender = “男” ;

​ 用XML 表示:

<student>
	<name>孙悟空name>
	<age>18age>
	<gender>gender>
student>

​ 现在已经被JSON 取代了

{"name":"孙悟空","age":18,"gender":"男"}

1.3 AJAX 的特点

1.3.1 AJAX 的优点

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

1.3.2 AJAX 的缺点

  • 没有浏览历史,不能回退
  • 存在跨域问题(同源)
  • SEO 不友好
    • 爬虫爬不到信息

1.4 AJAX 属性和方法

属性 描述
onreadystatechange 状态改变的事件触发器
readyState 对象状态(integer),状态值
0 = 未初始化,未调用send()方法
1 = 读取中,已调用send(),正在发送请求
2 = 已读取,send方法执行完成,接收到全部响应内容
3 = 交互中,正在解析响应内容
4 = 完成,响应内容解析完成
responseText 获得字符串形式的响应数据
responseXML 获得XML形式的响应数据
status 服务器返回的状态码,如:
404 = “文件未找到”
200 = “成功”
500 = “服务器内部错误”
304=“资源未被修改”
statusText 服务器返回的状态文本信息
timeout 指定请求超时时间,默认为 0 代表没有限制
ontimeout 绑定超时的监听
onerror 绑定请求网络错误的监听
方法 描述
abort() 停止当前请求
getResponseHeaders(“headerLabel”) 返回值指定响应首部(响应头)的串值
open(“method”, “url”, true) 建立对服务器的调用,method参数可以是GET、POST或PUT
url参数可以是相对URL或绝对URL 这个方法还包括3个可选参数
send(content) 向服务器发送请求
getAllResponseHeaders() 把 http 请求的所有响应首部(响应头)作为键/值对返回
setRequestHeader(“label”, “value”) 把指定首部设置为所提供的值 在设置任何首部之前必须先调用open()

2. HTTP相关问题

2.1 MDN 文档

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

2.2 HTTP 请求交互的基本过程

  • 前后应用从浏览器端向服务器发送HTTP 请求(请求报文)
  • 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
  • 浏览器端接收到响应, 解析显示响应体/调用监视回调
    【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第1张图片

2.3 HTTP 请求报文

  • 请求行 method url路径 http协议版本/1.1

    • GET /s?ie=utf-8 HTTP
    • POST /login
  • 请求头 键名: 键值

    • Host: www.baidu.com
    • Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
    • Content-Type: application/x-www-form-urlencoded 或者 application/json
    • User-Agent: chrome 83
  • 空行,必须有

  • 请求体

    • GET 请求体为空

    • POST 请求体可以不为空

    • username=tom&pwd=123

    • {"username": "tom", "pwd": 123}

GET 的请求报文

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第2张图片

POST 的请求报文

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第3张图片

2.4 HTTP 响应报文

  • 响应状态行 HTTP协议版本 响应状态码 响应状态字符串(不需要单独设置)

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

    • Content-Type: text/html;charset=utf-8
    • Content-Length: 2048
    • Content-encoding: gzip
    • Set-Cookie: BD_CK_SAM=1;path=/
  • 空行,必须有

  • 响应体,html 标签里的全部内容

    • html 文本/json 文本/js/css/图片...

GET 的响应报文

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第4张图片
【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第5张图片

POST 的响应报文

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第6张图片
【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第7张图片

2.5 post 请求体参数格式

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

2.6 响应状态码

状态码 状态码英文名称 中文描述
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

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

  • GET:从服务器端读取数据(查)

  • POST:向服务器端添加新数据 (增)

  • PUT:更新服务器端已经数据 (改)

  • DELETE:删除服务器端数据 (删)

2.8 API 的分类

  • REST API:restful (Representational State Transfer(资源)表现层状态转化)
    • 发送请求进行 CRUD 哪个操作由请求方式来决定
    • 同一个请求路径可以进行多个操作
    • 请求方式会用到GET/POST/PUT/DELETE
  • 非 REST API:restless
    • 请求方式不决定请求的 CRUD 操作
    • 一个请求路径只对应一个操作
    • 一般只有 GET/POST

2.9 区别:一般 http 请求与 ajax 请求

  • ajax 请求是一种特别的 http 请求

  • 对服务器端来说,没有任何区别,区别在浏览器端

  • 浏览器端发请求:只有 XHR 或 fetch 发出的才是 ajax 请求,其它所有的都是非 ajax 请求

  • 浏览器端接收到响应

    • 一般请求:浏览器一般会直接显示响应体数据,也就是我们常说的刷新/跳转页面
    • ajax 请求:浏览器不会对界面进行任何更新操作,只是调用监视的回调函数并传入响应相关数据

3 原生 AJAX 的基本使用 XHR

3.0 准备工作

3.0.1 安装 node.js

http://nodejs.cn/

3.0.2 安装 express(服务端框架)

https://www.expressjs.com.cn/

初始化环境

npm init --yes

下载express包

npm install express --save

编写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("服务已经启动, 8000 端口监听中...");
 })

运行 js 程序

node express基本使用.js

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第8张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第9张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第10张图片

3.0.3 安装 nodemon 自动重启工具

文件内容有修改自动重新启动服务

https://nodemon.io/

安装

npm install -g nodemon

启动服务

nodemon server.js

3.1 理解

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

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的

3.2 核心对象使用步骤

3.2.1 创建 XMLHttpRequest 对象

// 方法一:直接创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 方法二:兼容IE
var xhr = null;
if(window.XMLHttpRequest){
  // 标准模式下
  xhr = new XMLHttpRequest();
}else{
  // IE独有的ajax对象
  xhr = new ActiveXObject('Microsoft.XMLHTTP')
}

3.2.2 设置请求信息(请求方法和url)

// 请求方式
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

3.2.3 发送请求

xhr.send(body) //get请求不传 body 参数,只有post请求使用

3.2.4 接收响应(事件绑定,处理服务端返回的结果)

//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);
	}
}

3.3 GET 请求

点击返回响应信息

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第11张图片

创建两个文件,浏览器端使用的 html 文件服务器端使用的 js 文件

在这里插入图片描述

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 接收GET类型的请求,且路径为/server
app.get('/server', (request, response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应
    response.send('HELLO AJAX GET');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

启动服务

node server.js

前端页面 GET.html

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <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');
      // GET传参方法:参数写在url里
      xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
      // 3.发送
      xhr.send();
      // 4.事件绑定 处理服务端返回的结果
      xhr.onreadystatechange = function(){
        // 判断服务端是否返回了所有结果
        if (xhr.readyState === 4) {
          // 判断响应状态码
          // 2xx都表示成功,不只有200,判断条件可写成xhr.status >= 200 && xhr.status <= 200
          if (xhr.status === 200) {
            // 处理结果 行 头 空行 体
            // 响应行
            console.log(xhr.status);// 状态码
            console.log(xhr.statusText);// 状态字符串
            console.log(xhr.getAllResponseHeaders);// 所有响应头
            console.log(xhr.response);// 响应体

            // 设置result文本
            result.innerHTML = xhr.response;
          }
        }
      }
    }
  script>
body>
html>

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第12张图片

3.4 POST 请求

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

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第13张图片

服务器端 server.js 添加 post

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 接收POST类型的请求,且路径为/server
app.post('/server', (request, response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应
    response.send('HELLO AJAX POST');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

前端页面 POST.html

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajax POST请求title>
  <style>
    #result{
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  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();
      // POST传参方法:参数写在send方法里,书写格式随意
      // xhr.send('a=100&b=200&c=300');
      xhr.send('a:100&b:200&c:300');
      // 4.事件绑定
      xhr.onreadystatechange = function(){
        // 判断
        if (xhr.readyState === 4) {
          if(xhr.status === 200){
            // 处理服务端返回的结果
            result.innerHTML = xhr.response
          }
        }
      }
    })
  script>
body>
html>

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第14张图片

3.5 设置请求头信息

前端页面 POST.html

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajax POST请求title>
  <style>
    #result{
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  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');
      // 设置请求头
      // 预定义的请求头,e.g.设置请求体内容的类型
      xhr.setRequesHeader('Content-Type','application/x-www-from-urlencoded');
      // 自定义头信息
      xhr.setRequesHeader('name', 'ykyk');

      // 3.发送
      // xhr.send();
      // POST传参方法:参数写在send方法里,书写格式随意
      // xhr.send('a=100&b=200&c=300');
      xhr.send('a:100&b:200&c:300');
      // 4.事件绑定
      xhr.onreadystatechange = function(){
        // 判断
        if (xhr.readyState === 4) {
          if(xhr.status === 200){
            // 处理服务端返回的结果
            result.innerHTML = xhr.response
          }
        }
      }
    })
  script>
body>
html>

服务器端 server.js 添加 all,设置响应头允许自定义请求头

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 可以接收任意类型的请求,且路径为/server,可用来设置响应头允许自定义请求头
app.all('/server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    //设置响应体
    response.send('HELLO AJAX ALL');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

3.6 JSON 数据请求

前端页面 JSON.html

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajax JSON数据title>
  <style>
    #result{
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  style>
head>
<body>
  
  <div id="result">div>
  <script>
    // 获取元素对象
    const result = document.getElementById('result');
    // 绑定键盘按下事件
    window.onkeydown = function(){
      // 发送请求
      const xhr = new XMLHttpRequest();
      // 设置响应体数据类型
      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){
            // 处理服务端返回的结果
            // console.log(xhr.response);
            // result.innerHTML = xhr.response;
            // 手动对数据进行转化
            // let data = JSON.parse(xhr.response);
            // console.log(data);
            // result.innerHTML = data.name;
            // 自动转换
            console.log(xhr.response);
            result.innerHTML = xhr.response.name;
          }
        }
      }
    }
  script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 可以接收任意类型的请求,且路径为/json-server
app.all('/json-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    //设置响应体
    // response.send('HELLO AJAX JSON');
    // 响应一个数据
    const data = {
        name: 'lemon',
        age: '18'
    }
    // 对对象进行字符串转换
    let str = JSON.stringify(data);
    //设置响应体
    response.send(str);
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第15张图片

3.7 IE 缓存问题

前端页面 IE.html

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <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.addEventListener('click', function(){
      const xhr = new XMLHttpRequest();
      // 添加参数使得url每次都不同,e.g.时间戳
      xhr.open('GET', 'http://127.0.0.1:8000/ie?t=' + Date.now());
      xhr.send();
      xhr.onreadystatechange = function(){
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            result.innerHTML = xhr.response;
          }
        }
      }
    })
  script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 针对IE缓存
app.get('/ie', (request, response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应
    response.send('HELLO IE');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

3.8 请求超时与网络异常

前端页面 超时与网络异常.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>请求超时与网络异常title>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #90b;
        }
    style>
head>
<body>
    <button>点击发送请求button>
    <div id="result">div>
    <script>
        const btn = document.getElementsByTagName('button')[0];
        const result = document.querySelector('#result');

        btn.addEventListener('click', function(){
            const xhr = new XMLHttpRequest();
            // 超时设置 2s,正常获取数据
            // xhr.timeout = 2000;
            //超时设置 0.5s,获取数据失败
            xhr.timeout = 500;
            //超时回调
            xhr.ontimeout = function(){
                alert("请求超时, 请稍后重试!!");
            }
            //网络异常回调
            xhr.onerror = function(){
                alert("你的网络似乎出了一些问题!");
            }

            xhr.open("GET",'http://127.0.0.1:8000/delay');
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status >= 200 && xhr.status< 300){
                        result.innerHTML = xhr.response;
                    }
                }
            }
        })
    script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 延时响应
app.all('/delay', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        // 设置响应体
        response.send('延时响应');
    }, 1000)
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第16张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第17张图片

3.9 取消请求

前端页面 取消请求.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>取消请求title>
head>
<body>
    <button>点击发送button>
    <button>点击取消button>
    <script>
        //获取元素对象
        const btns = document.querySelectorAll('button');
        let x = null;
        
        btns[0].onclick = function(){
            x = new XMLHttpRequest();
            x.open("GET",'http://127.0.0.1:8000/delay');
            x.send();
        }

        // abort
        btns[1].onclick = function(){
            x.abort();
        }
    script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 延时响应
app.all('/delay', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        // 设置响应体
        response.send('延时响应');
    }, 1000)
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第18张图片

3.10 请求重复发送问题

前端页面 请求重复发送问题.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>重复请求问题title>
head>
<body>
    <button>点击发送button>
    <script>
        //获取元素对象
        const btns = document.querySelectorAll('button');
        let x = null;
        //标识变量
        let isSending = false; // 是否正在发送AJAX请求

        btns[0].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;
                }
            }
        }

        // abort
        btns[1].onclick = function(){
            x.abort();
        }
    script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 延时响应
app.all('/delay', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        // 设置响应体
        response.send('延时响应');
    }, 1000)
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第19张图片

4 jQuery 发送请求

4.1 get 请求

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

4.2 post 请求

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

url:请求的 URL 地址

data:请求携带的参数

callback:载入成功时回调函数

type:设置返回内容格式,xml html script json text _default

前端页面 client.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery 发送 AJAX 请求title>
    <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js">script>
head>
<body>
    <div class="container">
        <h2 class="page-header">jQuery发送AJAX请求 h2>
        <button class="btn btn-primary">GETbutton>
        <button class="btn btn-danger">POSTbutton>
        <button class="btn btn-info">通用型方法ajaxbutton>
    div>
    <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');
        });

        $('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('出错啦!!');
                },
                //头信息
                headers: {
                    c:300,
                    d:400
                }
            });
        });

    script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 延时响应
app.all('/delay', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        // 设置响应体
        response.send('延时响应');
    }, 1000)
});

// jQuery 服务
app.all('/jquery-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第20张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第21张图片

5 Axios 发送请求

前端页面 axios.html

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>axios 发送 AJAX请求title>
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js">script>
head>

<body>
    <button>GETbutton>
    <button>POSTbutton>
    <button>AJAXbutton>

    <script>
        // https://github.com/axios/axios
        const btns = document.querySelectorAll('button');

        //配置 baseURL
        axios.defaults.baseURL = 'http://127.0.0.1:8000';
      
				//GET 请求
        btns[0].onclick = function () {
            axios.get('/axios-server', {
                // 第二个参数--url参数
                params: {
                    id: 100,
                    vip: 7
                },
                // 第三个参数--请求头信息
                headers: {
                    name: 'atguigu',
                    age: 20
                }
            }).then(value => {
                console.log(value);
            });
        }
				//POST 请求
        btns[1].onclick = function () {
            axios.post('/axios-server',{
                // 第二个参数--请求体
                username: 'admin',
                password: 'admin'
            		},{
                // 第三个参数--url参数
                params: {
                    id: 200,
                    vip: 9
                },
                // 第四个参数--请求头信息
                headers: {
                    height: 180,
                    weight: 180,
                }
            });
        }
    		//AJAX 请求
        btns[2].onclick = function(){
            axios({
                //请求方法
                method : 'POST',
                //url
                url: '/axios-server',
                //url参数
                params: {
                    vip:10,
                    level:30
                },
                //头信息
                headers: {
                    a:100,
                    b:200
                },
                //请求体信息
                data: {
                    username: 'admin',
                    password: 'admin'
                }
            }).then(response => {
                //响应状态码
                console.log(response.status);
                //响应状态字符串
                console.log(response.statusText);
                //响应头信息
                console.log(response.headers);
                //响应体
                console.log(response.data);
            })
        }
    script>
body>

html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// axios 服务
app.all('/axios-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第22张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第23张图片

6 fetch 发送请求

https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch

前端页面 fetch.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>fetch 发送 AJAX请求title>
head>
<body>
    <button>AJAX请求button>
    <script>
        const btn = document.querySelector('button');

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

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// fetch 服务
app.all('/fetch-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第24张图片【AJAX 笔记】AJAX 基本、HTTP 基本、原生 AJAX 的使用,jQuery / Axios / fetch 发送请求、跨域(JSONP/CORS)_第25张图片

7 跨域

7.1 同源策略

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

前端页面 index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页title>
head>
<body>
    <h1>lemonh1>
    <button>点击获取用户数据button>
    <script>
        const btn = document.querySelector('button');

        btn.onclick = function(){
            const x = new XMLHttpRequest();
            // 这里因为是满足同源策略的, 所以 url 可以简写
            x.open("GET",'/data');
            // 发送
            x.send();
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    if(x.status >= 200 && x.status < 300){
                        console.log(x.response);
                    }
                }
            }
        }
    script>
body>
html>

服务器端 server.js

const express = require('express');

const app = express();

app.get('/home', (request, response)=>{
    // 响应一个页面
    response.sendFile(__dirname + '/index.html');
});

app.get('/data', (request, response)=>{
    response.send('用户数据');
});

app.listen(9000, ()=>{
    console.log("服务已经启动...");
});

7.2 JSONP

  • JSONP 是什么
    • JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get 请求
  • JSONP 怎么工作的
    • 在网页有一些标签天生具有跨域能力,比如:img link iframe script
    • JSONP 就是利用 script 标签的跨域能力来发送请求的

7.2.1 原理

前端页面 index.html

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原理演示title>
    <style>
        #result {
            width: 300px;
            height: 100px;
            border: solid 1px #78a;
        }
    style>
head>

<body>
    <div id="result">div>
    <script>
        // 处理数据
        function handle(data) {
            // 获取 result 元素
            const result = document.getElementById('result');
            result.innerHTML = data.name;
        }
    script>
    
    <script src="http://127.0.0.1:8000/jsonp-server">script>
body>

html>

服务器端 app.js

const data = {
    name: 'lemon'
};
handle(data);

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// jsonp服务
app.all('/jsonp-server',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        name: '尚硅谷atguigu'
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 返回结果
    response.end(`handle(${str})`);
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

7.2.2 JSONP 实践

前端页面 index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>案例title>
head>
<body>
    用户名: <input type="text" id="username">
    <p>p>
    <script>
        // 获取 input 元素
        const input = document.querySelector('input');
        const p = document.querySelector('p');
        
        // 声明 handle 函数
        function handle(data){
            input.style.border = "solid 1px #f00";
            // 修改 p 标签的提示文本
            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>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 用户名检测是否存在
app.all('/check-username',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        exist: 1,
        msg: '用户名已经存在'
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 返回结果
    response.end(`handle(${str})`);
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

7.2.3 jQuery 中的 JSONP

前端页面 index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery-jsonptitle>
    <style>
        #result{
            width:300px;
            height:100px;
            border:solid 1px #089;
        }
    style>
    <script crossorigin="anonymous" src='https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js'>script>
head>
<body>
    <button>点击发送 jsonp 请求button>
    <div id="result">

    div>
    <script>
        $('button').eq(0).click(function(){
            $.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data){
                $('#result').html(`
                    名称: ${data.name}
校区:
${data.city} `
) }); });
script> body> html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// jQuery中的JSONP
app.all('/jquery-jsonp-server',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        name:'lemon',
        city: ['北京','上海','深圳']
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 接收 callback 参数
    let cb = request.query.callback;

    // 返回结果
    response.end(`${cb}(${str})`);
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

7.3 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.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CORStitle>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #90b;
        }
    style>
head>
<body>
    <button>发送请求button>
    <div id="result">div>
    <script>
        const btn = document.querySelector('button');

        btn.onclick = function(){
            //1. 创建对象
            const x = new XMLHttpRequest();
            //2. 初始化设置
            x.open("GET", "http://127.0.0.1:8000/cors-server");
            //3. 发送
            x.send();
            //4. 绑定事件
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    if(x.status >= 200 && x.status < 300){
                        //输出响应体
                        console.log(x.response);
                    }
                }
            }
        }
    script>
body>
html>

服务器端 server.js

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// cors跨域
app.all('/cors-server', (request, response)=>{
    // 设置响应头
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", '*');
    response.setHeader("Access-Control-Allow-Method", '*');
    // response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
    response.send('hello CORS');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

8 完整的 server.js 代码

//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// 发送请求时,如果发送路径(请求行的第二个内容)是/server,就会执行函数体里的代码
// 接收GET类型的请求,且路径为/server
app.get('/server', (request, response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应
    response.send('HELLO AJAX GET');
});

// 接收POST类型的请求,且路径为/server
// app.post('/server', (request, response)=>{
//     // 设置响应头,设置允许跨域
//     response.setHeader('Access-Control-Allow-Origin', '*');
//     // 设置响应
//     response.send('HELLO AJAX POST');
// });

// 可以接收任意类型的请求,且路径为/server,可用来设置响应头允许自定义请求头
app.all('/server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    // 设置响应体
    response.send('HELLO AJAX ALL');
});

// 可以接收任意类型的请求,且路径为/json-server
app.all('/json-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    // 设置响应体
    // response.send('HELLO AJAX JSON');
    // 响应一个数据
    const data = {
        name: 'lemon',
        age: '18'
    }
    // 对对象进行字符串转换
    let str = JSON.stringify(data);
    // 设置响应体
    response.send(str);
});

// 针对IE缓存
app.get('/ie', (request, response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应
    response.send('HELLO IE');
});

// 延时响应
app.all('/delay', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        // 设置响应体
        response.send('延时响应');
    }, 1000)
});

// jQuery 服务
app.all('/jquery-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

// axios 服务
app.all('/axios-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

// fetch 服务
app.all('/fetch-server', (request, response) => {
    // 设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = {name:'lemon'};
    response.send(JSON.stringify(data));
});

// jsonp服务
app.all('/jsonp-server',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        name: '尚硅谷atguigu'
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 返回结果
    response.end(`handle(${str})`);
});

// 用户名检测是否存在
app.all('/check-username',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        exist: 1,
        msg: '用户名已经存在'
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 返回结果
    response.end(`handle(${str})`);
});

// jQuery中的JSONP
app.all('/jquery-jsonp-server',(request, response) => {
    // response.send('console.log("hello jsonp")');
    const data = {
        name:'lemon',
        city: ['北京','上海','深圳']
    };
    // 将数据转化为字符串
    let str = JSON.stringify(data);
    // 接收 callback 参数
    let cb = request.query.callback;

    // 返回结果
    response.end(`${cb}(${str})`);
});

// cors跨域
app.all('/cors-server', (request, response)=>{
    // 设置响应头
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", '*');
    response.setHeader("Access-Control-Allow-Method", '*');
    // response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
    response.send('hello CORS');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

你可能感兴趣的:(AJAX/JSONP,ajax,前端)