JSONP

JSONP (JSON with Padding) 是一种用于解决浏览器跨域请求的技术,它允许在不受同源策略限制的情况下,从其他域加载数据。其原理是利用 <script> 标签不受同源策略限制的特性,加载其他域下的脚本。

其他域即服务端所在的域,返回一个函数名由前端提供的函数执行表达式,<script> 标签请求 https://example.com/api/a?callback=callbackName,服务端返回 callbackName(data)

具体实现见 JSONP。后端以 Express 为例,对其使用进行说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// app.js
var express = require('express');
var api = require('./api/getData.js');
var app = express();

app.get('/getData', function (req, res) {
api.getData(req, res);
});

var server = app.listen(8081, function () {
var host = this.address().address;
var port = this.address().port;
console.log('应用实例,访问地址为 http://%s:%s', host, port);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// api/getData.js
function getData(req, res) {
var callback = req.query.callback,
num = req.query.num;

var data = [];
for (var i = 0; i < num; i++) {
data.push({ id: 'id' + i, name: 'Tracy' });
}

if (callback) {
res.type('text/javascript'); // 代码中必须规定从服务器返回数据的类型,代码res.type('text/javascript')被加在返回的数据之前用于告诉浏览器这是一段JavaScript代码
res.send(callback + '(' + JSON.stringify(data) + ')');
} else {
res.json(data);
}
}

exports.getData = getData;

前端代码:

1
2
3
4
5
6
7
8
9
getJSONP('./getData', { num: 2 }, function (data) {
var str = '<ul>';
for (var i = 0; i < data.length; i++) {
str += '<li>' + data[i].id + ':' + data[i].name + '</li>';
}
str += '</ul>';

document.body.innerHTML = str;
});

JSONP 只支持 GET 请求,它需要信任提供 JSONP 服务的服务器,容易受到恶意代码注入的攻击,存在安全性和可维护性方面的问题,已逐渐被跨域资源共享(CORS)所代替。