服务端响应JSON数据
创建文件server.js
// 1、引入express
const express = require('express');
// 2、创建应用对象
const app = express();
app.all('/json-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
// 响应一个数据
const data = {
name: 'atguigu'
};
// 对对象进行字符串转换
let str = JSON.stringify(data);
response.send(str);
});
// 4、监听端口,启动服务
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中..");
})
创建html文件
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #909090;
}
</style>
<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 && xhr.status < 300) {
// result.innerHTML = xhr.response;
// let data = JSON.parse(xhr.response);
// result.innerHTML = data.name;
result.innerHTML = xhr.response.name;
}
}
}
}
</script>
此时数据为JS格式字符串,若想修改为对象有两种方法
方法一手动转化:在if条件输出里面修改为(代码注释部分)
let data = JSON.parse(xhr.response);
result.innerHTML =data.name;
方法二自动转化—设置响应体数据类型
xhr.responseType = 'json';//new方法下添加设置
result.innerHTML = xhr.response.name;//输出方式修改
都可以返回结果,注意大小写和拼写可能为undefined
nodemon自动重启工具安装
由于前面的请求发送中,我们每次都要重启服务,或手动终止特别麻烦,所以此处安装自动工具,之后修改js中send内容就会自动保存,免于来回重启server,会对AJAX的请求结果进行缓存,会导致使用本地缓存而非服务器最新数据
操作如下:
1、在vs终端输入 npm install -g nodemon(红色报错可改为nodemon.cdm server.js)
出现found 0 vulnerabilities表示新版node自带,已经下载好了
2、重启服务nodemon server.js即可
提示:后续文章内容中所修改的server.js部分都是直接在方法下添加,即创建对象和启动服务之间
请求超时与网络异常处理
需要大家手动添加#result的css样式,随意即可,只要能显示出内容
<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();
// 超时设置,若2000内无结果则取消
xhr.timeout = 2000;
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>
沿用上面的server.js部分,在下方输入
// 延时响应
app.all('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
setTimeout(() => {
response.send('延时响应');
}, 1000)
});
前面安装了自动重启下方终端就会自动保存
点击发送请求之后,即会弹出请求超时的异常提示框
其中网络异常部分是不需要大家拔网线滴~只需要在谷歌浏览器这个位置
将节流模式改为离线模式,即为断网状态,点击发送按钮后也会弹出警示框
AJAX请求的手动取消
<button>点击发送</button>
<button>点击取消</button>
<script>
const btns = document.querySelectorAll('button');
let x = null;//声明设置在函数外,let生效与当前作用域
btns[0].onclick = function () {
x = new XMLHttpRequest();
x.open('GET', 'http://127.0.0.1:8000/delay');
x.send();
}
//abort方法进行取消请求,其属于AJAX对象
btns[1].onclick = function () {
x.abort();
}
</script>
server.js部分与前面延迟响应一致无需修改
可以通过点击和取消,查看控制台的输出情况
请求重复发送
问题:当用户重复点击发送请求,创建多个请求致使服务器压力大
方法:对相同请求进行取消,创建一个最新的请求,缓解服务器压力
<button>点击发送</button>
<script>
const btns = document.querySelectorAll('button');
let x = null;
let isSending = false;
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();
// 在完成请求之后,即状态为4时
x.onreadystatechange = function () {
if (x.readyState === 4) {isSending = false;
//不加状态码判断,可能请求为失败请求,在成功条件里判断就无法修改变量}}}
</script>
通过不断点击按钮,查看控制台就会发现,服务器始终只有一个数据请求
jQuery发送AJAX请求
首先第一步是jQuery文件引进
浏览器输入:BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务
搜索:输入jQuery并点击,找到jquery.min.js后缀,复制script标签粘贴即可
注:在复制的cdn前添加 crossorigin="anonymous" 可防止报文报错
此处我没有使用bootstrap框架,便自己写了一个样
<style>
h2 {width: 1200px;margin-top: 50px;padding-bottom: 10px;
font-size: 30px;border-bottom: 1px solid gray;}
button {border-radius: 5px;height: 35px;width: 100px;
background-color: skyblue;float: left;margin-right: 10px;
color: white;border: none;text-align: center;}
.btn-primary {background-color: #3587cf;}
.btn-danger {background-color: rgb(12, 190, 226);}
</style>
<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">通用型方法</button>
</div>
</body>
接下来便是JS代码,若是有多个文件夹,注意server.js放在外层并重新启动服务
前两个为之前所学的GET和POST请求方法
$('button').eq(0).click(function(){
$.get('http://localhost:8000/jquery-server', {a:100, b:200}, function(data){console.log(data)}, 'json')})
//表示响应体是一个json格式的数据
$('button').eq(1).click(function(){
$.post('http://localhost:8000/jquery-server', {a:100, b:200}, function(data){console.log(data)})})
$('button').eq(2).click(function(){
$.ajax({
url:'http://localhost:8000/jquery-server',
data:{a:100, b:222},//参数
type:'GET',//请求类型
dataType:'json',//响应体结果
//成功的回调
success:function(data){console.log(data)},
timeout:2000,//超时时间
//失败的回调
error:function(){console.log('出错了')},
//头信息设置
headers:{
c:300,
d:400
}})})
server.js部分
//jQuery服务
app.all('/jquery-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: 'chan' };
// response.send('Hello jQuery AJAX');
response.send(JSON.stringify(data));
});
其返回结果一个是对象,一个是字符串
Axios发送AJAX请求
与jQuery相同的方式引入CDN,添加 crossorigin="anonymous"
<style>
button {border-radius: 5px;height: 35px;width: 100px;
background-color: skyblue;float: left;
margin-right: 10px;color: white;border: none;text-align: center;}
.btn-primary {background-color: #3587cf;}
.btn-danger {background-color: rgb(12, 190, 226);}
</style>
<button class="btn btn-primary">GET</button>
<button class="btn btn-danger">POST</button>
<button class="btn btn-info">AJAX</button>
<script>
const btns = document.querySelectorAll('button');
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: 'chan',age: 20}
}).then(value => {console.log(value);});}
btns[1].onclick = function () {
//post请求中,第一个参数url,第二个请求体,第三个其余配置
axios.post('/axios-server', {
username: 'admin',
password: 'admin'
}, {//url参数
params: {id: 200,vip: 9},
//请求头参数
headers: {name: 'chan',age: '20'},
//请求体
})}
// axios函数发送请求
btns[2].onclick = function () {
axios({method: 'POST',url: 'axios-server',
//url参数
params: {vip: 10,leve: 30},
//头信息
headers: {a: 100,b: 200},
//请求体参数
data: {name: 'chan',age: '20'}
}).then(response => {
console.log(response);
// 响应状态码
console.log(response.status);
//响应状态字符串
console.log(response.statusText);
// 响应头信息
console.log(response.headers);
// 响应体
console.log(response.data);
})}</script>
server.js部分
//axios服务
app.all('/axios-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: 'chan' };
// response.send('Hello jQuery AJAX');
response.send(JSON.stringify(data));
});
同源策略
AJAX默认遵循策略—即协议、域名、端口号完全相同
违背同源策略也称为跨域,http/https协议、8000/5500端口、a.com/b.com这种两者间的请求,即为跨域
新建一个文件夹,单独的放入index与server,
<h1>chan Hi</h1>
<button>点击获取用户数据</button>
<script>
const btn = document.querySelector('button');
btn.onclick = function () {
const x = new XMLHttpRequest();
x.open('GET', 'http://127.0.0.1:9000/data');
x.send();
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
console.log(x.response);
}
}
}
}
</script>
过程中,我研究了好久也不明白为什么我的需要设置跨域和完整URL的问题
无论是vs打开还是端口都报错,希望有懂的大佬可以分析一下
新建的server下代码
const express = require('express');
const app = express();
app.get('/home', (request, response) => {
response.sendFile(__dirname + '/index.html');
});
app.get('/data', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
response.send('用户数据');
});
app.listen(9000, () => {
console.log('端口9000服务已经启动');
});
jsonp
此处依然是新建一个jsonp文件夹
这边先看代码,后面原理再进行阐述
<style>
div {width: 100px;height: 100px;border: 1px solid #78a;}</style>
<!-- jsonp不受同源策略限制,通过get方式执行后端返回的js脚本 -->
<div id="res"></div>
<script>
function handle(data) {
const res = document.getElementById('res');
res.innerHTML = data.name;
}
</script>
<script src="http://127.0.0.1:8000/jsonp-server"></script>
文件夹中额外添加一个app.js
const data = {
name: 'chan'
};
console.log(data);
handle(data);
但不需要新建js文件,写回之前的server.js中即可
//jsonp 服务
app.all('/jsonp-server', (requesr, response) => {
const data = { name: 'chan' }
//设置响应
let str = JSON.stringify(data)
// response.send('console.log("hello jsonp")')
response.send(`handle(${str})`)
//此处非引号而是esc下放的反引
})
其个人所理解的原理是:(若有理解错误的地方,欢迎指正)
首先jsonp不受同源策略限制
/jsonp-server返回的是一个函数调用handle(),此处函数的形参就是实参chan
也就是我们想要返回给用户的数据,随后再让前端中提前声明好的函数handle进行处理
jsonp实践
前面原理没有看懂也没有关系,下面的实践内容帮助你进一步理解
如下面的例子,用户输入用户名,由于没有数据库等内容,无论用户输入什么,我们都让其返回‘用户已存在’,这就是我们所想要给用户返回的数据
用户名:<input type="text" id="username">
<p></p>
<script>
const input = document.getElementById('username')
const p = document.querySelectorAll('p')[0]
function handle(data) {
input.style.border = "solid 1px #f00"
p.innerHTML = data.msg}//修改p标签的提示文本
//失去焦点事件
input.onblur = function () {
let username = this.value
//向服务端发送请求;1 设置script标签
const script = document.createElement('script')
//2 设置标签的src属性
script.src = 'http://localhost:8000/check-username'
//3 将script插入文档中
document.body.appendChild(script)}
</script>
//用户名检测是否存在
app.all('/check-username', (requesr, response) => {
const data = {
exist: 1,
msg: '用户名已经存在'
}
let str = JSON.stringify(data)
response.send(`handle(${str})`)
})
//用户名检测是否存在
app.all('/jquery-jsonp-server', (request, response) => {
const data = {
name: 'chan',
age: 20
}
//设置响应
let str = JSON.stringify(data)
//接受callback参数
let cb = request.query.callback
response.send(`${cb}(${str})`)
})
此时无论输入什么形式都会显示已存在
如果本文存在内容遗漏、说明不清或是有问题的地方,欢迎大家提出一起解决,也希望本文对大家有所帮助