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头浏览器才会执行 }