Ajax(Asynchronous JavaScript And XML)

通过ajax浏览器可以像服务器发送异步请求,最大的优势:可以在不刷新网页的情况下,异步的向后台发送请求,在前端接受并展示数据

本次学习所用到的插件

  1. Node.js
  2. NPM
  3. express(简单的web服务器)
  4. nodemon(用于自动重启node服务器)

XML

  1. XML是什么? 有什么用?

    1. XML 被设计用来传输和存储数据
    2. XML 的设计宗旨是传输数据(XML),而非显示数据(HTML)
    3. XML 被设计为具有自我描述性
    4. XML 标签没有被预定义。您需要自行定义标签
  2. 语法:

    <?xml version="1.0" encoding="utf-8">
    <root>
    <!-- 标签可以自由命名 -->
    <name>Fitz</name> <!-- 必须正确关闭标签 -->
    </root>
    <root>
    <!-- 属性必须加引号 -->
    <!-- 尽量不要使用属性 -->
    <name gender="male">Fitz</name>
    <address province="GD">HouJie</address>
    </root>
    <root>
    <!-- 这是错误的属性使用方法 -->
    <attr attr1="error" attr2="wrong">属性不应该这样用</attr>
    </root>
    <root>
    <!-- 特殊的符号应该使用实体 -->
    <sample>使用实体例如:大于号 &gt;</sample>
    </root>

JSON

由于JSON 比 XML 更小、更快,更易解析。所以现在AJAX返回的数据格式多是使用JSON

{
"name": "Fitz",
"hobby": "computer science",
"dream": "good at math"
}

关于AJAX

  1. ajax的优点

    1. 无需刷新页面即可与服务器进行通讯
    2. 允许根据用户事件来更新部分页面内容
  2. ajax的缺点
    1. 没有浏览历史,这就导致不能回退
    2. 存在跨域问题
    3. 对SEO不友好

HTTP协议

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

  • 请求报文

    • 重要格式与参数
    行    ====>  GET/POST  /s?ie=utf-8  HTTP/1.1
    头 ====> Host: baidu.com
    Cookie: name=trash
    content-type: application/x-www-form-urlencoded
    user-Agent: chrome 83
    空行 ====>
    体 ====> username=root&password=root
  • 响应报文

  • 重要格式与参数

    行    ====>  HTTP/1.1  200  OK
    头 ====> Host: baidu.com
    content-type: text/html;charset=utf-8
    content-length: 2048
    空行 ====>
    体 ====> <html>
    <head></head>
    <body></body>
    </html>

AJAX重点之XMLHttpRequest对象

XMLHttpRequest对象作用是前端向服务端发送ajax请求,别接收来自服务端的数据

``` javascript {.line-numbers}
//主要步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest(); // 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server'); // 3 发送请求
xhr.send(); // 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`);
}else{
console.log('Some Error !');
}
}
```

关于 onreadystatechange与readyState

每当 readyState 改变时,就会触发 onreadystatechange 事件,readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪

服务端 实例

使用插件 express

//引入express
const express = require("express"); //创建应用对象
const app = express(); //创建路由规则
app.get('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息');
}) app.post('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息 -post method');
}) app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})

ajax-get 实例

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title> <style> * {
margin: 0;
padding: 0;
} #result{
width: 200px;
height: 100px;
border: solid 1px black;
} </style> </head>
<body>
<button>点击发送请求</button>
<div id="result"></div> <script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server?name=fitz');
// 3 发送请求
xhr.send();
// 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`); //展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>

ajax-post 实例

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title> <style> * {
margin: 0;
padding: 0;
} #result{
width: 200px;
height: 100px;
border: solid 1px black;
} </style> </head>
<body>
<button>点击发送请求</button>
<div id="result"></div> <script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
// 3 发送请求
xhr.send('name=Fitz&gender=Male'); //post请求参数应在send方法中添加
// 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`); //展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>

设置请求头信息

// 2  初始化   设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 3 发送请求
xhr.send('name=Fitz&gender=Male');

服务端响应JSON数据

方法一

前端代码

var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法一
//通过手动转换来响应JSON
let data = JSON.parse(xhr.response);
console.log(data);
div.innerHTML = data.username;
}
}
}
}

方法二

前端代码

var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法二
//自动转换
console.log(xhr.response);
div.innerHTML = xhr.response.username;
}
}
}
}

后端代码

//引入express
const express = require("express");
const { json } = require("body-parser"); //创建应用对象
const app = express(); // //创建路由规则
app.all('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.setHeader('Access-Control-Allow-Header','*') //要发送回去前端的数据
const data = {
username: 'root',
password: 'root123'
} const data2str = JSON.stringify(data); //手动将data对象转换为JSON字符串
response.send(data2str); //send方法只能接收一个字符串
}) app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})

AJAX关于在IE中的缓存问题

解决方法:使用时间戳以保证每次的URL都不一样(参数不一样)

var xhr = new XMLHttpRequest();
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 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}

超时设置、回调与网络异常的回调

var xhr = new XMLHttpRequest();
//设置超时
xhr.timeout = 2000;
//设置超时回调
xhr.ontimeout = function(){
console.log('你的网络似乎有些慢');
}
//设置断网回调
xhr.onerror = function(){
console.log('你的网络似乎有些问题');
}
xhr.open("GET",'http://127.0.0.1:8000/cancel); //使用时间戳
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}

取消ajax请求

var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var div = document.getElementById('result'); var xhr = null; addEventListener('click',function(){
if(xhr){
xhr.abort();
}
xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/cancel');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}
}) btn2.onclick = function(){
xhr.abort();
}

jquery发送ajax请求

$(function(){
//get
$('button').eq(0).click(function(){
$.get('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
},'json')
}) //post
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
})
}) //通用方法
$('button').eq(2).click(function(){
$.ajax({
//url
url: 'http://127.0.0.1:8000/jquery',
//要发送的参数
data: {
a: 'a',
b: 'b'
},
//ajax请求类型
type: 'GET',
//指定响应体的类型
dataType: 'json',
//设置超时时间
timeout: 2000,
//成功的回调
success: function(data){
console.log(data);
},
//失败的回调
error: function(e){
console.log(e);
},
//设置头部信息
headers: {
a: 200
}
})
})

fetch函数发送ajax请求

fetch('http://127.0.0.1:8000/fetch?test=ok',
{
//请求方法
method: 'POST',
//请求头
headers: {
name: 'Da'
},
//请求体
body: 'username=tri4123'
}).then((response)=>{
console.log(response);
return response.text();
//可以自动解析响应体为JSON格式的数据
// return response.json();
}).then((response=>{
console.log(response);
})
);

跨域

同源策略:协议、域名、端口号 必须完全相同

违背同源策略的称之为跨域

解决跨域

使用具备跨域特性的标签:<img> <script> <link> <iframe>

  1. 使用jsonp:在前段定义处理函数,供后端调用

    前端代码

    //在前段设置处理函数,供后端调用
    <script>
    //处理数据的函数
    function handleData(data){
    //获取result元素
    var result = document.getElementById('result');
    result.innerHTML = data.name;
    }
    </script> <!-- <script src="./jsonp.js"></script> -->
    <script src="http://127.0.0.1:8000/jsonp-server"></script>

    后端代码

    const express = require("express");
    const app = express();
    app.all('/jsonp-server',(request,response)=>{
    var PersonInfo = {
    name: 'Lx'
    } //调用前端已经定义好的函数
    //就能将后端数据跨域传给前端
    response.end(`handleData(${JSON.stringify(PersonInfo)})`)
    // response.send('console.log("jsonp实验成功")')
    })
  2. jquery(原理还是jsonp)

    前端代码


    //callback=? 参数是必须的,这会在前端注册一个函数 供后端调用
    $.getJSON('http://127.0.0.1:8000/server?callback=?',function(){
    //后端的数据....
    })

    后端代码

    const express = require("express");
    const app = express();
    app.all('/server',(request,response)=>{
    var PersonInfo = {
    name: 'Lx'
    } //获取在前端注册的callback函数
    var callbackFunc = request.query.callback; //调用前端已经定义好的函数
    //就能将后端数据跨域传给前端
    response.end(`${callbackFunc}(${JSON.stringify(PersonInfo)})`);
    })
  3. CORS 跨域资源共享 官方的跨域方案

CORS通过在服务端设置一个响应头告诉前端,该请求是否允许跨域,浏览器收到响应头后会对响应进行放行

后端代码

//允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
response.setHeader('Access-Control-Allow-Methods','*');

看完我的笔记不懂也会懂----Ajax的更多相关文章

  1. 看完我的笔记不懂也会懂----bootstrap

    目录 Bootstrap笔记 知识点扫盲 容器 栅格系统 源码分析部分 外部容器 栅格系统(盒模型)设计的精妙之处 Bootstrap笔记 写在开始: 由于我对AngulaJS的学习只是一个最浅显的过 ...

  2. 看完我的笔记不懂也会懂----AngulaJS

    目录 Angular.js学习笔记 ng-app(指令) ng-model ng-init angular之表达式 双向数据绑定 数据流向的总结 作用域对象 控制器对象 依赖对象与依赖注入 命令式与声 ...

  3. 看完我的笔记不懂也会懂----git

    Git学习笔记 - 什么是Git - 首次使用Git - DOS常用命令 - Git常用命令 - 关于HEAD - 版本回退 - 工作区.暂存区与版本库 - git追踪的是修改而非文件本身 - 撤销修 ...

  4. 看完我的笔记不懂也会懂----Node.js

    Node.js 学习 - 命令行窗口 - 进程与线程 - ECMAScript的缺点 - Node模块化 - Node中的全局对象 - 包 package - NPM包管理器 (Node Packag ...

  5. 看完我的笔记不懂也会懂----javascript模块化

    JavaScript模块化 模块化引子 模块化的历史进化 模块化规范 CommonJS规范 Node.js(服务器端) 下项目的结构分析 browerify(浏览器端) 下项目的结构分析 AMD规范 ...

  6. 看完我的笔记不懂也会懂----less

    目录 Less学习 语法篇 注释 变量 映射(Maps) @规则嵌套和冒泡 less中的嵌套规则 less中的混合 less的运算 extend延伸/继承 less忽略编译(转义) 导入(Import ...

  7. 看完我的笔记不懂也会懂----MongoDB

    MongoDb数据库学习 - 数据库的分类 - 数据库基本概念 - MongoDB常用指令 - MongoDB的CURD - sort({key:*[1,-1]}).limit(num).skip(n ...

  8. 看完我的笔记不懂也会懂----MarkDown使用指南

    目录 语法 [TOC] 自动生成目录 1. 标题 2. 文本强调 3. 列表 4. 图片 5. 超链接 6. 文本引用 7. 分割线 8. 代码 9. 任务列表 (MPE专属) 10. 表格 11. ...

  9. 看完我的笔记不懂也会懂----ECMAscript 567

    目录 ECMAscript 567 严格模式 字符串扩展 数值的扩展 Object对象方法扩展 数组的扩展 数组方法的扩展 bind.call.apply用法详解 let const 变量的解构赋值 ...

随机推荐

  1. SPOJ 227 Ordering the Soldiers

    As you are probably well aware, in Byteland it is always the military officer's main worry to order ...

  2. Codeforces Round #646 (Div. 2) B. Subsequence Hate (思维,前缀和)

    题意:给你一个只含有\(0\)和\(1\)的字符串,每次操作可以将\(0\)改成\(1\)或\(1\)改成\(0\),问最少操作多少次,使得子序列中不含有\(010\)和\(101\). 题解:仔细想 ...

  3. 牛客编程巅峰赛S1第5场 - 青铜&白银 A.凯撒密码(字符串)

    题意:给你一个加密的字符串,以及偏移量,求对应的明文. 题解:根据样例,不难看出模板串是:\(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopq ...

  4. Java基础(第二期)

    数据类型扩展以及面试题讲解 整数拓展:进制 int i=10; int i2=010; //八进制0 int i3=0x10; //十六进制0x 0~9 A~F 16 相关进制转换自行学习,用的不多 ...

  5. 国产网络损伤仪SandStorm -- 如何连接设备

    国产网络损伤仪SandStorm可以模拟出带宽限制.时延.时延抖动.丢包.乱序.重复报文.误码.拥塞等网络状况,在实验室条件下准确可靠地测试出网络应用在真实网络环境中的性能,以帮助应用程序在上线部署前 ...

  6. 在Blazor Server 项目中使用 EF Core Sqlite

    按照教程创建了一个 Blazor Server 项目 教程地址: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/build-a-blaz ...

  7. Dubbo SPI 机制源码分析(基于2.7.7)

    Dubbo SPI 机制涉及到 @SPI.@Adaptive.@Activate 三个注解,ExtensionLoader 作为 Dubbo SPI 机制的核心负责加载和管理扩展点及其实现.本文以 E ...

  8. 【Azure 微服务】基于已经存在的虚拟网络(VNET)及子网创建新的Service Fabric并且为所有节点配置自定义DNS服务

    问题描述 创建新的Service Fabric集群,可以通过门户,Powershell命令,或者是ARM模板.但是通过门户和PowerShell命令时,创建的SF集群都会自动新建一个虚拟网络而无法使用 ...

  9. leetcode 122 123 309 188 714 股票买卖 动态规划

    这类问题有一个通法 https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/solution/yi-ge-tong-y ...

  10. flagcounter 被禁用...

    源地址 https://s11.flagcounter.com/count2/arWz/bg_FFFFFF/txt_000000/border_CCCCCC/columns_2/maxflags_14 ...