【问】jsonp是什么?实现原理?
【答】
jsonp背景:
jsonp出现的背景是由于浏览器对ajax同源策略限制(协议、域名、端口号必须相同),无法访问非同源数据,但script标签请求的资源,却无此限制。正是由于这个原因,可借助script实现跨域请求,这种请求数据的方案我们叫它jsonp。jsonp原理分析:
- 前端动态创建一个script标签,src指向请求地址并添加dataType=jsonp&callback=jp1(和后端约定好dataType=jsonp代表这是这是jsonp请求,这时给我返回的应该是一个方法调用,方法名从callback参数中取。本例中就应该返回jp1(555),比如555为后端要响应给前端的数据)
- 前端事先定义好,window.jp1 = function (res) {console.log(res)},此函数为前端拿到res结果后想要处理的逻辑。
- 该script组装完毕并发出请求后,后端返回’jp1(555)'并会被script自动执行。由于是script标签,它会把响应内容当作js来执行(就像scipit引入第三方js库时,它拿到返回后的字符串后会马上执行)
【扩展1】jsonp实现示例?
//1. jsonp工具实现示例
function jsonp(option, cb){
// 示例参数
// option = {
// url: 'http://www.baidu.com/api',
// dataType: 'jsonp',
// param: {
// a: 1,
// callback: 'jp1'
// }
// },
// cb = function (res) {
// console.log('后端返回', res)
// }
// 动态创建 script 标签
var jpscript = document.createElement("script")
// 约定callback的值作为返回调用的函数名
jpscript.src="http://www.baidu.com/api?dataType=jsonp&callback=jp1&a=1" //根据option组装成该格式
// 向页面添加 script 标签
document.body.appendChild(oscript)
// 实现定义好该函数,后端返回scrip请求后将触发该函数
window['jp1'] = function (res){ //根据option命名回掉函数名称,函数体为参数cb
console.log(res)
//优化:可在这销毁掉刚才动态创建的script
}
}
// 2. 前端调用示例
jsonp(
{
url: 'http://www.baidu.com/api',
dataType: 'jsonp',
param: {
a: 1,
}
},
function (res){
console.log('后端返回了', res)
}
)
// 3. 后端实现示例, nodejs
const express = require('express');
const app = express();
app.get('/api', (req, res) => {
// 1 判断如果是jsonp的话,应该返回一个函数调用
if(req.dataType == 'jsonp'){
// 此处为后端根据入参的处理逻辑,比如根据req.query.a=1响应的后端数据如下
let data = {
name: '张三',
age: 22
};
// 拼接一个函数调用的字符串
let Str = `${req.query.callback}(${JSON.stringify(data)})`;
// 把拼接好的字符串交给script解析
res.send(Str);
}
// 2 非jsonp请求...
});
参考1: jsonp 原理详解及 jsonp-pro 源码解析
参考2:Node.js 实现jsonp详解
参考3:jsonp解决跨域请求—nodejs写后端