JSONP 的原理是利用了浏览器加载 JavaScript 资源文件时不受同源策略的限制而实现的。
具体实现方式:
-
全局注册一个函数,
window.jsonpCallback = (data) => console.log(data)
-
构造一个请求
目标地址?callback=jsonpCallback
-
构造一个
script
标签,将src
属性设置为上一步构造的请求地址,然后将 script 标签插入 DOM 中。
/** 示例 */
function jsonp(url){
return new Promise((resolve, reject) => {
window.jsonpCallback = (data) => {
resolve(data);
}
const script = document.createElement('script');
script.src = `${url}?callback=jsonpCallback`;
script.onload = () => {
script.remove()
}
script.onerror = () => {
reject(new Error('error'))
}
document.body.appendChild(script);
})
}
// 发送请求
jsonp("http://localhost:8888/data").then(response => {
console.log("这是 JSONP");
console.log(response);
});
- 服务器端构造一个 JavaScript 函数调用表达式并返回。
/** 使用 Node.js 做服务端来做一个示例 */
/**
...
*/
if (path === '/data') {
response.statusCode = 200;
response.setHeader("Content-Type", "text/javascript;charset=utf-8");
const string = `window['{{xxx}}']({{data}})`
// 使用json 数据做一个数据模拟
const data = fs.readFileSync("./public/data.json").toString();
// 构造返回一个函数调用表达式 window.jsonpCallback(data)
const finalString = string.replace("{{data}}", data).replace('{{xxx}}', query.callback);
response.write(finalString);
response.end();
}
/**
...
*/
- 浏览器会加载并执行上述返回的代码(
window.jsonpCallback(data)
)。