JSONP(跨域SRJ)
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以通过Server Rendered JavaScript的方式从别的域名(网站)那获取资料,即跨域读取数据。
JSONP是通过动态创建script标签,script标签指向响应方(服务器)来实现的,而动态script标签只能GET不能POST,所以JSONP不能POST。
JSONP简单过程:
1.请求方(浏览器)创建script标签,script标签指向响应方(服务器),同时传递查询参数?callback=xxx,xxx为函数名;
2.响应方根据查询参数(获取方式query.callback),构造形如:
xxx.call(undefined,response);
xxx(response);
的响应;
3.请求方接收到响应,就会执行xxx.call(undefined,response)或xxx(response),这样就拿到了返回数据response。
这就是JSONP。
一般,会将传递的查询参数声明为window的一个属性window[函数名],函数名是随机数,并且需要删除创建的动态script标签和函数,可以这样实现:
script.onload = function (e) {
e.currentTarget.remove();
delete window[函数名];
}
后端代码
else if (path === '/pay' && method === 'GET') {
let amount = fs.readFileSync('./db.txt', 'utf-8');
let newAmount = amount - 1;
fs.writeFileSync('./db.txt', newAmount, 'utf-8');
response.setHeader('Content-Type', 'application/javascript;charset=utf-8');
response.statusCode = 200;
response.write(`${query.callback}(
{"success":true,
"left":${newAmount}}
)`);
response.end();
}
响应方(服务器)收到名为'/pay'的GET请求后,会读取db文件,将db文件中的内容(数字-1)后作为新数字,存入db文件,设置响应头为'application/javascript;charset=utf-8'格式,状态码为200,响应内容为用{"success":true,"left":${newAmount}}调用查询参数对应的函数,响应结束。
请求方(浏览器)接收到响应后,就会执行相应的函数,这样就得到了{"success":true,"left":${newAmount}}。
前端代码
原生JS
let amount = document.querySelector('#amount');
let btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
let functionName = 'blame' + parseInt(Math.random() * 100000, 10);
window[functionName] = function (response) {
amount.innerText = response.left;
}
let script = document.createElement('script');
script.src = `./pay?callback=${functionName}`;
document.body.appendChild(script);
script.onload = function (e) {
e.currentTarget.remove();
delete window[functionName];
}
})
jQuery:
jQuery实现JSONP语法非常简单,实现同样效果,只需:
$('#btn').on('click', function () {
$.ajax({
url: 'http://localhost:8001/pay',
dataType: 'jsonp',
success: function (response) {
$('#amount').text(response.left);
}
})
})