「前端早读君003」手把手教你实现一个通用的jsonp跨域方法
什么是jsonp
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
以上内容来自百度,不太理解不要紧,记住最重要的一点是:通过script标签引入的链接,接口返回的内容是被当成js代码来进行解析的。请大家记住这一点,很重要的特性。
创建一个简单的jsonp服务器
下面是一个基于nodejs的简单的服务器,如果不了解nodejs也没关系,大家看下注释,理解下作用就可以
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') } })
创建完服务器以后,我们接下来开始书写一个jsonp
/** * @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: jsonp
获取更多知识,请微信扫码关注公众号关注早读君,每天早晨为你推送前端知识,度过挤地铁坐公交的时光。
而且不定时举办活动赠送书籍哦
相关推荐
zmosquito 2020-05-10
somebodyoneday 2020-04-22
fengchao000 2020-04-22
fengchao000 2020-04-11
fengchao000 2020-03-05
xiaouncle 2020-02-13
adonislu 2019-07-01
fengchao000 2020-06-17
adonislu 2020-05-16
adonislu 2020-05-10
Richardxx 2020-03-07
somebodyoneday 2020-03-06
somebodyoneday 2020-02-16
baijinswpu 2020-01-29
fengchao000 2020-01-10
fengchao000 2019-12-25
newthon 2019-12-23