乐趣区

jsonp完整实现

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 头浏览器才会执行
  }
退出移动版