JSONP,全称JSON with Padding。为解决 GET 请求跨域。
跨域常用方案:CORS。
JSONP 基于两个原理:
- 动态生成
script,使用script.src地址来跨域; script.src加载的脚本内容为 JSONP:即 PADDING(JSON) 格式。
注意:在 GET 的 URL 中,查询参数包含callback,callback值是一个方法,方法的 形参 就是获取到的服务端数据。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>简单 JSONP </title></head><body><input type="text"><button onclick="handleSend()">Send</button><ul class="main"></ul><script src="./index.js"></script><script>function handleData(res) {const liEl = document.createElement('li')liEl.innerText = res.msgconst ulEl = document.getElementsByClassName('main')ulEl[0].appendChild(liEl)const inputEl = document.getElementsByTagName('input')inputEl[0].value = ''}function handleSend() {const inputEl = document.getElementsByTagName('input')const sendData = { id: Math.floor(Math.random() * 10), msg: inputEl[0].value || '' }jsonp({url: 'http://127.0.0.1:10010',params: sendData,onData: handleData});}</script></body></html>
function stringify(params) {const obj = Object.entries(params)const qs = obj.map(([k, v])=> {let noVal = falseif(v === null || v === undefined || typeof v === 'object') {noVal = true}return `${encodeURIComponent(k)}=${noVal ? '' : encodeURIComponent(v)}`}).join('&')return qs}function jsonp({url, onData, params}) {const scriptEl = document.createElement('script')// 1.函数随机名称,避免全局污染const cbFnName = 'JSONP_PADDING' + Math.random().toString().slice(2)// 2.默认 callback 为 cbFnNamescriptEl.src = `${url}?${stringify({ callback: cbFnName, ...params })}`// 3.使用 onData 作为回调函数,接收服务端响应数据window[cbFnName] = onDatadocument.body.appendChild(scriptEl)}
const http = require('http');const url = require('url');const qs = require('querystring')const server = http.createServer((req, res) => {const {pathname, query} = url.parse(req.url)const params = qs.parse(query)console.info('params', params)const data = {msg: params.msg, id: params.id}if(params.callback) {const str = `${params.callback}(${JSON.stringify(data)})`res.end(str)} else {res.end()}})server.listen(10010, () => console.info('server.....'))
