JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。因为同源策略,通常来讲位于 server1.example.com 的网页没法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页能够获得从其余来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并非 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。前端
以上内容来自百度,不太理解没关系,记住最重要的一点是:经过script标签引入的连接,接口返回的内容是被当成js代码来进行解析的。请你们记住这一点,很重要的特性。node
下面是一个基于nodejs的简单的服务器,若是不了解nodejs也不要紧,你们看下注释,理解下做用就能够git
const http = require('http') const url = require('url') const jsonpServer = http.createServer((req, res) => { let data = { status: true, msg: 'hello jsonp' } const body = url.parse(req.url, true) // jsonp请求中会包含一个callback参数,例如 http://baidu.com.js?callback=hello // 获取请求的url中的callback参数的值,callback是一个函数名 const callback = body.query.callback // 将对象数据转为字符串 data = JSON.stringify(data) // 拼接成js代码 // 举个例子,假设这个callback回调的名字是 test // 拼接完就是 test({status: true,msg: 'hello jsonp'}) // 显然,就是一段js代码,做用就是执行这个函数 const js = `${callback}(${data})` // 返回js代码给客户端 res.end(js) }) jsonpServer.listen('3000', (err) => { if (!err) { console.log('server is running at localhost:3000') } })
/** * @description 建立一个随机的函数名 * @return {string} */ const createCallbackName = function () { return `callback${(Math.random() * 1000000).toFixed(0)}` } /** * @description 插入一个script标签 * @param url {string} */ const insertScript = function (url) { let script = document.createElement('script') script.onload = script.onerror = function () { document.body.removeChild(script) } script.setAttribute('src', url) document.body.appendChild(script) } /** * @description 拼接字符串参数 * @param url {string} url * @param data {object} 要拼接的query数据 * @return url {string} 拼接完成后的新url */ const setQuery = function (url, data) { const keys = Object.keys(data) if (keys.length === 0) { return url } else{ const pairs = keys.map(key => `${key}=${data[key]}`) url = url.includes('?') ? url : `${url}?` url += pairs.join('&') return url } } /** * @description jsonp函数 * @param url {string} 请求地址 * @param config {object} 接口配置设置 * @return {Promise} */ const jsonp = function (url, config = {}) { let data = config.data || {} let timeout = config.timeout || 5000 let timer const funcName = createCallbackName() data.callback = funcName return new Promise((resolve, reject) => { window[funcName] = function (res) { if (timer) { clearTimeout(timer) } delete window[funcName] resolve(res) } url = setQuery(url, data) timer = setTimeout(() => { delete window[funcName] reject(new Error(`fetch ${url} fail`)) }, timeout) insertScript(url) }) } // 使用效果 jsonp('http://localhost:3000') .then(res => { console.log(res) }) .catch(err => { console.log(err) })
获取更多知识,请微信扫码关注公众号关注早读君,天天早晨为你推送前端知识,度过挤地铁坐公交的时光。
并且不定时举办活动赠送书籍哦github