跨域(非同源策略请求)
- 同源策略请求
ajax / fetch
部署到服务器上 - xampp 修改本地的host文件
请求http://127.0.0.1:1234/index.html
相当于请求http://api.qq.com/getData
127.0.0.1:1234 http://api.qq.com/
- 服务器拆分
web服务器:静态服务kbs.sports.qq.com
data服务器:业务逻辑和数据分析api.sports.qq.com
图片服务器 - 三者一样就是同源,只要有一个不同就是跨域
协议
域名
端口号 - 只有访问类型为
xhr(XMLHttpRequest)
的才会出现跨域
JSONP
- 服务器可以响应js代码
app.all('/jsonp-server', (request, response) =>{ const data = { name: 'Nliver的学习笔记-1' }; //将数据转化为字符串 let str = JSON.stringify(data); //返回结果形式 是一个函数调用,而函数的实参就是我们想给客户端返回的结果数据 response.end(`handle(${str})`); });
- 客户端提供handle函数
<!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>
在jQuery中使用JSONP
- 客户端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jQuery-jsonp</title> <style> #result { width: 300px; height: 100px; border: solid 1px #089; } </style> <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <button>点击发送 jsonp 请求</button> <div id="result"> </div> <script> // 在callback中填写处理函数 $('button').eq(0).click(function(){ $.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data){ // console.log(data); $('#result').html(` 名称: ${data.name}<br /> 校区: ${data.city} `) }) }); </script> </body> </html>
- 服务器端
//jQuery服务中的jsonp app.all('/jquery-jsonp-server', (request, response) =>{ // response.send('console.log("hello jsonp")'); const data = { name: 'Nliver', city: ['北京', '上海', '深圳'] }; //将数据转化为字符串 let str = JSON.stringify(data); //接收 callback 参数 let cb = request.query.callback; //返回结果 response.end(`${cb}(${str})`); });
示例:
- 后端实现
const Koa = require("koa"); const fs = require("fs"); const app = new Koa(); app.use(async (ctx, next) => { if (ctx.path === "/api/jsonp") { const { cb, msg } = ctx.query; ctx.body = `${cb}(${JSON.stringify({ msg })})`; return; } }); app.listen(8080);
- 普通js示例:
<script type="text/javascript"> window.jsonpCallback = function(res) { console.log(res); }; </script> <script src="http://localhost:8080/api/jsonp?msg=hello&cb=jsonpCallback" type="text/javascript" ></script>
JQuery Ajax 示例:
- 第一种;
<script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script> <script> $.ajax({ url: "http://localhost:8080/api/jsonp", dataType: "jsonp", type: "get", // 传过去的数据 data: { msg: "hello" }, // 相当于上面的cb,对应的函数就是下面的success jsonp: "cb", success: function(data) { console.log(data); } }); </script>
- 第二种前端代码:
$.ajax({ url: 'http://127.0.0.1:8001/list', method: 'get', dataType: 'jsonp', // 执行的是JSONP请求 success: res => { console.log(res); } });
- 后端代码:
app.get('/list', (req, res) => { let { callback = Function.prototype // 如果不存在这个函数的话,默认值 } = req.query; let data = { code: 0, messageL '哈哈' }; res.send(`${callback}(${JSON.stringify(data})`); });
callback = ...
是jQuery帮我们创建多的一个全局函数,当返回的时候全局函数执行,会帮助我们把success执行