回顾JSONP的概念与特点
概念: 浏览器通过<script>标签的src属性,请求服务器上的数据,同时服务器返回一个函数的调用,这种请求数据的方式叫做JSONP
特点:
- JSONP不属于真正的Ajax请求,因为他没有使用XMLHttpRequest这个对象
- JSONP仅支持GET请求,不支持POST, PUT, DELETE等请求
创建JSONP接口的注意事项
如果项目已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP接口,否则JSONP接口会被处理成开启了CORS的接口,示例代码如下:
//优先创建JSONP接口(不会被处理成CORS接口)
app.get('/api/jsonp', (req, res) => {})
//再配置 CORS 中间件(后续接口都会被配置成CORS接口)
app.use(CORS())
//这是一个开启了CORS的接口
app.get('/api/get', (req, res) => {})
实现JSONP接口的步骤
- 获取客户端发送过来的回调函数的名字
- 得到要通过JSONP形式发送给客户端的数据
- 根据前两步得到的数据,拼接出一个函数调用的字符串
- 把上一步得到的字符串相应给客户端的<script>标签进行解析执行
实现JSONP接口具体代码
//必须在CORS中间件之前 配置JSONP接口
append.get('/api/jsonp', (req, res) => {
//获取到客户端发送过来的回调函数的名字
const funcName = req.query.callback;
//得到要通过 JSONP 形式发送给客户端的数据
const data = { name: 'zs', age: 20 };
//根据前两步得到的数据 拼接处一个函数调用的字符串
const scriptStr = `${funcName}(${JSON.stringify(data)})`;
//把上一步得到的字符串相应给客户端的<script>标签进行解析执行
res.send(scriptStr);
})
在网页中使用jQuery发起JSONP请求
使用 $.ajax() 函数,提供JSONP的配置选项,从而发起JSONP请求测试上述代码,示例代码如下:
//发起JSONP请求
$('#btnJsonp').on('click', function() {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/jsonp',
dataType: 'jsonp',
success: function(res) {
console.log(res);
}
})
})
完整代码
测试接口的网页
<!DOCTYPE html>
<html lang="zh-CN">
<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>Document</title>
<script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.js"></script>
</head>
<body>
<button id="btnGet">GET</button>
<button id="btnPost">POST</button>
<button id="btnDelete">DELETE</button>
<button id="btnJsonp">JSONP</button>
<script>
$(function() {
//测试GET接口
$('#btnGet').on('click', function() {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/get',
data: {
name: 'zs',
age: 20
},
success: function(res) {
console.log(res);
}
})
})
//测试POST接口
$('#btnPost').on('click', function() {
$.ajax({
type: 'POST',
url: 'http://127.0.0.1/api/post',
data: {
bookname: '水浒传',
author: '黄志健'
},
success: function(res) {
console.log(res);
}
})
})
//为删除按钮绑点击事件
$('#btnDelete').on('click', function() {
$.ajax({
type: 'DELETE',
url: 'http://127.0.0.1/api/delete',
success: function(res) {
console.log(res);
}
})
})
//发起JSONP请求
$('#btnJsonp').on('click', function() {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/jsonp',
dataType: 'jsonp',
success: function(res) {
console.log(res);
}
})
})
})
</script>
</body>
</html>
自定义模块
const { append } = require('vary');
const express = require('../module/node_modules/express/lib/express.js');
const router = express.Router();
router.get('/get', (req, res) => {
//通过 req.query 获取客户端通过查村字符串 发送到服务器的数据
const query = req.query;
//调用 res.send() 方法 向客户端响应处理的结果
res.send({
status: 0, //0表示处理成功 1表示处理失败
msg: 'GET请求成功!', //状态的描述
data: query //需要相应给客户端的数据
})
})
router.post('/post', (req, res) => {
//通过 req.body 获取客户端的请求体中 发送到服务器 URL-encoded 格式的数据
const body = req.body;
//调用 res.send() 方法
res.send({
status: 0,
msg: 'POST请求成功!',
data: body
})
})
//定义DELETE接口
router.delete('/delete', (req, res) => {
res.send({
status: 0,
msg: 'DELETE请求成功!'
})
})
module.exports = router;
服务器
//导入express模块
const express = require('../module/node_modules/express/lib/express.js');
//创建apiRouter路由模块
const apiRouter = express.Router();
//创建express服务器实例
const app = express();
//配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }));
//必须在CORS中间件之前 配置JSONP接口
app.get('/api/jsonp', (req, res) => {
//获取到客户端发送过来的回调函数的名字
const funcName = req.query.callback;
//得到要通过 JSONP 形式发送给客户端的数据
const data = { name: 'zs', age: 20 };
//根据前两步得到的数据 拼接处一个函数调用的字符串
const scriptStr = `${funcName}(${JSON.stringify(data)})`;
//把上一步得到的字符串相应给客户端的<script>标签进行解析执行
res.send(scriptStr);
})
//在路由之前配置 cors 中间件 从而解决接口跨域问题
const cors = require('cors');
app.use(cors());
//导入路由模块
const router = require('./apiRouter');
//把路由模块注册到app上
app.use('/api', router);
//调用 app.listen方法 指定端口号并开启服务器
app.listen(80, () => {
console.log('Express server running at http://127.0.01');
});