- 跨域
- 同源策略
- 代码演示
- 跨域使用AJAX
- 解决跨域问题方法一:CORS
- 解决方法二:JSONP
- 封装JSONP[扩展]
-曾老湿, 江湖人称曾老大。
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
跨域
跨域的关键知识点:
同源策略 浏览器故意设计的一个功能限制
CORS 突破浏览器限制的一个方法
JSONP
IE时代的妥协
同源策略
什么是同源? |
---|
window.origin或location.origin可以得到当前源。
代码语言:javascript复制window.origin
"https://www.baidu.com"
location.origin
"https://www.baidu.com"

源=协议 域名 端口号
如果两个URL的协议
,域名
,端口号
完全一致,那么这两个url就是同源的
例如:
https://www.qq.com https://www.baidu.com 不同源 http://www.baidu.com https://www.baidu.com 不同源 完全一致,才算同源
同源策略定义 |
---|
浏览器规定,如果JS运行在源A里,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨域访问。
例如: 架设 driverzeng.com/index.html 引用了 linuxgc.com/1.js 那么就说 1.js 运行在源driverzeng.com里 注意:这跟linuxgc.com没有关系,虽然1.js从那个域名下载。 所以1.js就只能获取driverzeng.com的数据 不能获取www.driverzeng.com或download.driverzeng.com的数据
这是浏览器的功能,浏览器故意这么设计的。
浏览器为什么这样做?
用来保护用户的隐私。
我们试想,如果没有同源策略,会怎样?
以QQ空间为例 源:https://user.qzone.qq.com 假设,当前用户已经登录(用cookie) 假设,AJAX请求/friends.json就可以获取用户好友列表 到目前为止都很正常
黑客来了 假设你的女神分析https://user.qzone-qq.com给你。 实际上这是一个钓鱼网站,你点开这个网页,这个网页也去请求你的好友列表 https://user.qzone.qq.com/friends.json 请问,你的好友列表是不是就就被黑客,偷摸的偷走了?
问题的根源 |
---|
无法区分发送者 QQ空间面里的JS和黑客网页里面的JS发的请求几乎没有区别(Referer有区别),如果后台开发者没有检查referer那么就完全没有区别。所以,没有同源策略,任何页面都能偷QQ空间的数据,甚至支付宝余额
那检查referer不就好了? 安全原则,安全链条的强度取决于最弱一环,万一这个网站后端开发,是一个傻X呢?所以浏览器应该主动预防这种投数据的行为,总之,浏览器是为了用户隐私,设置了严格的同源策略。
同源策略总结:不同源的页面之间,不准互相访问数据
代码演示
创建两个网站:
qq-com里面有一个server.js,用来模拟QQ空间。 driverzeng-com里面有一个server.js,用来模拟坏人网站


qq-com: /index.html 是首页 /qq.js 是JS脚本文件 /friend.json 是模拟好友数据 端口:8888 URL:http://127.0.0.1:8888
打开qq-com目录,里面创建server.js文件,写入代码
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(`
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="/x">
</head>
<body>
<h1>曾老湿</h1>
<script src="/y"></script>
</body>
`)
response.end()
} else if(path === '/x'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
response.write(`body{color: red;}`)
response.end()
} else if(path === '/y'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(`console.log('这是JS内容')`)
response.end()
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)
zls-com: /index.html 是首页 /zls.js 是JS脚本文件 端口:9999 URL:http://127.0.0.1:9999
打开zls-com目录,里面创建server.js文件,写入代码

启动服务,创建两个终端:
先创建QQ,启动服务

代码语言:javascript复制MacBook-pro:qq-com driverzeng$ node-dev server.js 8888
再创建ZLS,启动服务

代码语言:javascript复制MacBook-pro:zls-com driverzeng$ node-dev server.js 9999
打开浏览器分别访问:
http://127.0.0.1:8888

http://127.0.0.1:9999

完善QQ页面 |
---|

server.js
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)
index.html
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QQ空间</title>
</head>
<body>
欢迎来到xxx的QQ空间
</body>
</html>

qq.js
代码语言:javascript复制console.log('qq.js')

friends.json
代码语言:javascript复制[
{"name":"邓紫棋"},
{"name":"吴彦祖"},
{"name":"彭于晏"},
{"name":"周杰伦 "}
]

完善zls页面 |
---|

server.js
代码语言:javascript复制
index.html
代码语言:javascript复制<!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>
说了你可能不信,我特么的是黑客
</body>
</html>

zls.js
代码语言:javascript复制console.log('zls')

跨域使用AJAX
正常使用AJAX,在qq.com:8888里运行JS可以访问到/friend.json
index.html
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QQ空间</title>
</head>
<body>
欢迎来到xxx的QQ空间
<script src="qq.js"></script>
</body>
</html>
qq.js
代码语言:javascript复制const request = new XMLHttpRequest()
request.open('GET','friends.json')
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status < 400){
console.log(request.response)
}
}
}
request.send()

黑客偷数据,在zls.com:9999里运行JS,不能访问!浏览器需要CORS
index.html
代码语言:javascript复制<!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>
说了你可能不信,我特么的是黑客
<script src="zls.js"></script>
</body>
</html>
zls.js
代码语言:javascript复制const request = new XMLHttpRequest()
request.open('GET','http://127.0.0.1:8888/friends.json')
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status < 400){
console.log(request.response)
}
}
}
request.send()

解决跨域问题方法一:CORS
问题根源,浏览器默认不同源之间不能相互访问数据,但是qq.com和zls.com都是我的网站,我是老板,我就想让两个公司的资源做共享,你作为一个浏览器,你凭阻止?
浏览器:emmm... 那行吧,那我给你一个方法,你要是想共享数据,那就需要提前声明。
哦?是吗?那我要怎么声明呢?
浏览器:你要跟qq.com这个网站说一声,在响应头里写上zls.com可以访问。
哦?是吗?那具体语法呢?
浏览器:Access-Control-Allow-Origin:http://zls.com mmp,都在文档里,不好去MDN看吗?
走起,后台服务设置一波:
server.js
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else if(path === '/friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'application/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
response.write(fs.readFileSync('public/friends.json'))
response.end()
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)


解决方法二:JSONP
有了第一种解决办法,为啥还需要第二种呢?是因为第二种方法更好么?
这个时候IE浏览器不得不问你一句话:你猜,我支不支持CORS?
Fuck,这还用猜?IE 6 7 8 9,白扯,前端开发的噩梦,兼容IE。
老板:我特么的就要兼容IE。
你:...我(qu)这(ni)就(da)去(ye)做(de)
JSONP |
---|
定义
JSONP跟JSON半毛钱关系都没有,由于前端水平低下,错误的将其称为JSONP
面临问题
程序猿常常面临奇葩需求 没有CORS,怎么跨域? 记不记得我们可以随意引用JS 虽然我们不能 访问qq.com:8888/friends.json 但是我们能引用qq.com:8888/friends.json啊 这有什么用?JS又不是数据 我们让JS包含数据不就好啦?试试看吧,明天就要上线了。
首先我们在qq.com中创建一个friends.js

先占个位,然后在server.js中添加路由
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else if(path === '/friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'application/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
response.write(fs.readFileSync('public/friends.json'))
response.end()
} else if(path === '/friends.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('public/friends.js').toString()
const data = fs.readFileSync('public/friends.json').toString()
const string2 = string.replace('{{ data }}',data)
response.write(string2)
response.end()
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)

可以发现,这并不是一个合法的JS,这个只是数据,所以我们需要在friends.js里面加上一赋值
代码语言:javascript复制window.zls = {{ data }}

这才是一个合法的JS,然后我们使用zls.js调用JS
代码语言:javascript复制const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
document.body.appendChild(script)


我们还可以监听JS的onload事件
代码语言:javascript复制const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
script.onload = () =>{
console.log(window.zls)
}
document.body.appendChild(script)

一开始我说,这个跟JSON一点关系都没有,为啥呢?因为我们可以把数据改成别的,不一定非得是JSON,可以是XML,HTML...
friends.js
代码语言:javascript复制window.zls = `<xml>曾老湿</xml>`

那是不是就可以叫,XMLP?
那如果里面的数据是3呢?
代码语言:javascript复制window.zls = 3

卧槽,细思极恐~~~~~~~~ 不知道该叫啥。不知所措。
话说回来,CORS的方法,可以设置白名单,指定谁能访问,还是挺安全的,但是...JSONP没有办法指定啊。mmp,这怎么搞?那我们就只能从判断referer开始入手了。
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else if(path === '/friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'application/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
response.write(fs.readFileSync('public/friends.json'))
response.end()
} else if(path === '/friends.js'){
if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('public/friends.js').toString()
const data = fs.readFileSync('public/friends.json').toString()
const string2 = string.replace('{{ data }}',data)
response.write(string2)
response.end()
}else{
response.statusCode = 404
response.end()
}
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)


优化 |
---|
window.zls 这样不就写死了么?那空间还有其他函数调用朋友的名字,比如,最近访客,比如,评论的人,比如,好友生日...
所以我们要定义一个随机数给函数,给url添加一个查询参数
zls.js
代码语言:javascript复制const random = Math.random()
window[random] = (data) =>{
console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload = () =>{
console.log(window.zls)
}
document.body.appendChild(script)
server.js
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else if(path === '/friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'application/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
response.write(fs.readFileSync('public/friends.json'))
response.end()
} else if(path === '/friends.js'){
if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
response.statusCode = 200
console.log(query.functionName)
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('public/friends.js').toString()
const data = fs.readFileSync('public/friends.json').toString()
const string2 = string.replace('{{ data }}',data)
response.write(string2)
response.end()
}else{
response.statusCode = 404
response.end()
}
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)


这样一来,我们查询参数和后台的server.js就可以配合了,然后我们在后台,获取到这个functionName,做个替换。
friends.js
代码语言:javascript复制window['{{ zls }}'] ({{ data }})
server.js
代码语言:javascript复制var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
if(!port){
console.log('请指定端口号好不啦?nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var pathWithQuery = request.url
var queryString = ''
if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
var path = parsedUrl.pathname
var query = parsedUrl.query
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' pathWithQuery)
if(path === '/index.html'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
var accept = request.headers["accept"];
console.log("accept:");
console.log(accept);
response.write(fs.readFileSync('public/index.html'))
response.end()
} else if(path === '/qq.js'){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('public/qq.js'))
response.end()
} else if(path === '/friends.json'){
response.statusCode = 200
response.setHeader('Content-Type', 'application/json;charset=utf-8')
response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
response.write(fs.readFileSync('public/friends.json'))
response.end()
} else if(path === '/friends.js'){
if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('public/friends.js').toString()
const data = fs.readFileSync('public/friends.json').toString()
const string2 = string.replace('{{ data }}',data).replace('{{ zls }}',query.functionName)
response.write(string2)
response.end()
}else{
response.statusCode = 404
response.end()
}
} else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
server.listen(port)
console.log('监听 ' port ' 成功n请用在空中转体720度然后用电饭煲打开 http://localhost:' port)


这样每次都是随机数了,就不会被写死了。但是也可能随机会随机到相同的或者跟别的开发,'撞衫'了,怎么办呢?
那我们就在随机数前面加一个前缀,保证不会重复
zls.js
代码语言:javascript复制const random = 'zlsFunctionNameJSONPbalala' Math.random()
window[random] = (data) =>{
console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload = () =>{
console.log(window.zls)
}
document.body.appendChild(script)

问题又来了,我们每发一次请求,就会多加载一个js文件。

怎么办呢?我们既然能创建script也能删除。
代码语言:javascript复制const random = 'zlsFunctionNameJSONPbalala' Math.random()
window[random] = (data) =>{
console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload = () =>{
script.remove()
}
document.body.appendChild(script)

这个就叫做...过河拆桥,emmm... 我们先创建script,拿到数据后,我们就可以把它删掉了。
封装JSONP[扩展]
代码语言:javascript复制function jsonp(url){
return new Promise((resolve,reject)=>{
const random = 'zlsFunctionNameJSONPbalala' Math.random()
window[random] = (data) =>{
resolve(data)
}
const script = document.createElement('script')
script.src = `${url}?functionName=${random}`
script.onload = () =>{
script.remove()
}
script.onerror = ()=>{
reject()
}
document.body.appendChild(script)
})
}
使用jsonp
代码语言:javascript复制jsonp('http://127.0.0.1:8888/friends.js')
.then((data)=>{
console.log(data)
})