适用范围:

  • 运行在浏览器中的html

1. 缺点:

  • 需要后端适配
    • 后端需要返回js代码
  • 不能发送post请求, 只能是get请求

梗概:

  • 一种进行跨域请求的方式
  • 一种投机取巧的方式

大致原理:

  • 利用html中script标签可以导入跨域脚本的特性
  • 服务端http返回js代码
    • 通常是一个函数调用
      • 该函数是在前端定义的一个全局回调函数
      • 后端把数据作为实参,传入给回调函数中
  • script通过http请求获取服务端返回的js代码, 并执行,在回调函数中就能接受到数据

实例

原生JS实现:

 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);
    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

服务端返回如下(返回时即执行全局函数):

handleCallback({"success": true, "user": "admin"})

jquery Ajax实现:

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",  // 自定义回调函数名
    data: {}
});

Vue axios实现:

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

后端node.js代码:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;
    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');
    res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');