jsonp 是实现前端跨域请求的常用方案,其内部原理是使用动态创建 script 标签来进行跨域请求(只能 get),这里写下完整实现
// 根据回调函数,重新创建随机的全局函数,避免全局函数管理冲突
function creatCallFun(fn){var callbackName = randomStr(10) // 随机生成字符串名称
window[callbackName] = function(args){fn.call(null, args)
}
return callbackName
}
// 参数转化
function creatScriptQuery(url, params){var querys = [];
for(let key in params){querys.push(key+'='+params[key])
}
return 'url?'+querys.join('&')
}
// 随机生成规定长度的随机字符串,这里用来生成随机的函数名
function randomStr(len){
var codes = 'abcdefghijklmnopqrstuvwxyz';
var l = len, s='';
while (l>0){s += codes[Math.floor(Math.random() * codes.length)]
l--
}
return s
}
// 动态创建 script 标签,插入到文档中
function loadScript(url, params, callfn){var script = document.createElement('script');
var path = creatScriptQuery(url, params);
var callbackName = creatCallFun(callfn) // 随机回调函数名
script.src = path + '&callback=' + callbackName;
document.body.appendChild(script)
script.onload = function(){window[callbackName] = null; // 加载完成进行销毁
// 还要将 script 消除
}
}
函数调用发送一个请求
loadScript('http://127.0.0.1:7001/test',{name: 123}, function(data){console.log(data)
})
服务端返回 callback 函数包裹的数据
// @router(/test)
async index() {const { ctx} = this;
let query = ctx.query
ctx.body = query.callback + '(' + JSON.stringify({ success: false}) +')';
ctx.set('content-type', 'text/javascript'); // 设置 header 头浏览器才会执行
}