概念:
浏览器通过script标签的src属性,请求服务器上的数据,同时服务器返回一个函数的调用,这种请求数据的方式叫做JSONP
如果项目中已经配置了CORS跨域资源共享,为防止冲突,必须在配置CORS中间件之前声明JSONP的接口,否则JSONP接口会被处理成开启了CORS的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const express=require('express')
const app=express()
const apirouter=require('./apirouter')
app.get('/api/jsonp',(req,res)=>{ const funcName=req.query.callback const data={name:'zs',age:20} const scriptStr=`${funcName}(${JSON.stringify(data)})` res.send(scriptStr)
}) app.use(express.urlencoded({extended:false}))
const cors=require('cors') app.use(cors())
app.use('/api',apirouter) app.listen(80,()=>{ console.log('运行在http://127.0.0.1') })
|
发请求:HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <!DOCTYPE html> <html lang="en"> <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.min.js"> </script> </head> <body> <button id="btnJsonp">Jsonp</button> <script> $('#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>
|
JSONP调用是通过动态创建script元素并为src属性指定跨域URL实现的,此时script和img元素类似,能够不受限制地从其他域加载资源,因为JSONP是有效的JavaScript,所以JSONP响应在被加载完成之后会立即执行,比如以上例子中,服务器返回了带有src的script标签,客户端·收到响应后,就会去请求http://127.0.0.1/api/jsonp?callback(data)数据
缺点:
- JSONP是从不同域拉取可执行代码,如果这个域不可信,则可能在响应中加入恶意内容
- 不好确定JSONP请求是否失败,虽然HTML5规定了script元素的onerror时间处理程序,但还没有被任何浏览器实现,为此,开发者经常需要使用计时器决定是否放弃等待响应