头条面试官:一文彻底搞懂JSONP

 一个正常的请求: JSON

为企业提供成都网站设计、做网站、网站优化、成都全网营销推广、竞价托管、品牌运营等营销获客服务。成都创新互联拥有网络营销运营团队,以丰富的互联网营销经验助力企业精准获客,真正落地解决中小企业营销获客难题,做到“让获客更简单”。自创立至今,成功用技术实力解决了企业“网站建设、网络品牌塑造、网络营销”三大难题,同时降低了营销成本,提高了有效客户转化率,获得了众多企业客户的高度认可!

正常发请求时,curl 示例:

 
 
 
 
  1. $ curl https://shanyue.tech/api/user?id=100
  2. {
  3.   "id": 100,
  4.   "name": "shanyue",
  5.   "wechat": "xxxxx",
  6.   "phone": "183xxxxxxxx"
  7. }

使用 fetch 发送请求,示例:

 
 
 
 
  1. const data = await fetch('https://shanyue.tech/api/user?id=100', {
  2.   headers: {
  3.     'content-type': 'application/json',
  4.   },
  5.   method: 'GET',
  6. }).then(res => res.json())

请求数据后,使用一个函数来处理数据

 
 
 
 
  1. handleData(data)

一个 JSONP 请求

JSONP,全称 JSON with Padding,为了解决跨域的问题而出现。虽然它只能处理 GET 跨域,虽然现在基本上都使用 CORS 跨域,但仍然要知道它,毕竟面试会问。

curl 示例

 
 
 
 
  1. $ curl https://shanyue.tech/api/user?id=100&callback=padding
  2. padding({
  3.   "id": 100,
  4.   "name": "shanyue",
  5.   "wechat": "xxxxx",
  6.   "phone": "183xxxxxxxx"
  7. })

对于正常的请求有何不同一目了然: 多了一个 callback=padding, 并且响应数据被 padding 包围,这就是 JSONP

那请求数据后,如何处理数据呢?此时的 padding 就是处理数据的函数

 
 
 
 
  1. window.padding = handleData

这里实现一个 jsonp 函数

 
 
 
 
  1. function jsonp_simple ({ url, onData, params }) {
  2.   const script = document.createElement('script')
  3.   // 一、默认 callback 函数为 padding
  4.   script.src = `${url}?${stringify({ callback: 'padding', ...params })}`
  5.   // 二、使用 onData 作为 window.padding 函数,接收数据
  6.   window['padding'] = onData
  7.   document.body.appendChild(script)
  8. }

此时会有一个问题: window.padding 函数会污染全局,如果有多个请求发送如何处理?

使 jsonp 的回调函数名作为一个随机变量,代码如下

 
 
 
 
  1. function jsonp ({ url, onData, params }) {
  2.   const script = document.createElement('script')
  3.   // 一、为了避免全局污染,使用一个随机函数名
  4.   const cbFnName = `JSONP_PADDING_${Math.random().toString().slice(2)}`
  5.   // 二、默认 callback 函数为 cbFnName
  6.   script.src = `${url}?${stringify({ callback: cbFnName, ...params })}`
  7.   // 三、使用 onData 作为 cbFnName 回调函数,接收数据
  8.   window[cbFnName] = onData;
  9.   document.body.appendChild(script)
  10. }
  11. // 发送 JSONP 请求
  12. jsonp({
  13.   url: 'http://localhost:10010',
  14.   params: { id: 10000 },
  15.   onData (data) {
  16.     console.log('Data:', data)
  17.   }
  18. })

代码附录

完整代码可见山月博客的 github 仓库: https://github.com/shfshanyue/blog/tree/master/code/jsonp/

JSONP 实现完整代码:

 
 
 
 
  1. function stringify (data) {
  2.   const pairs = Object.entries(data)
  3.   const qs = pairs.map(([k, v]) => {
  4.     let noValue = false
  5.     if (v === null || v === undefined || typeof v === 'object') {
  6.       noValue = true
  7.     }
  8.     return `${encodeURIComponent(k)}=${noValue ? '' : encodeURIComponent(v)}`
  9.   }).join('&')
  10.   return qs
  11. }
  12. function jsonp ({ url, onData, params }) {
  13.   const script = document.createElement('script')
  14.   // 一、为了避免全局污染,使用一个随机函数名
  15.   const cbFnName = `JSONP_PADDING_${Math.random().toString().slice(2)}`
  16.   // 二、默认 callback 函数为 cbFnName
  17.   script.src = `${url}?${stringify({ callback: cbFnName, ...params })}`
  18.   // 三、使用 onData 作为 cbFnName 回调函数,接收数据
  19.   window[cbFnName] = onData;
  20.   document.body.appendChild(script)
  21. }

JSONP 服务端适配相关代码:

 
 
 
 
  1. const http = require('http')
  2. const url = require('url')
  3. const qs = require('querystring')
  4. const server = http.createServer((req, res) => {
  5.   const { pathname, query } = url.parse(req.url)
  6.   const params = qs.parse(query)
  7.   const data = { name: 'shanyue', id: params.id }
  8.   if (params.callback) {
  9.     str = `${params.callback}(${JSON.stringify(data)})`
  10.     res.end(str)
  11.   } else {
  12.     res.end()
  13.   }
  14. })
  15. server.listen(10010, () => console.log('Done'))

JSONP 页面调用相关代码

 
 
 
 
  1.   
  2.   
  3.   
  4.   
  5.   jsonp({
  6.     url: 'http://localhost:10010',
  7.     params: { id: 10000 },
  8.     onData (data) {
  9.       console.log('Data:', data)
  10.     }
  11.   })
  12.   

JSONP 实现代码示例演示

从中克隆代码: 山月博客的 github 仓库

文件结构

  • index.js: jsonp 的简单与复杂实现
  • server.js: 服务器接口形式
  • demo.html: 前端如何调用 JSONP

快速演示

 
 
 
 
  1. // 开启服务端
  2. $ node server.js
  3. // 对 demo.html 起一个服务,并且按照提示在浏览器中打开地址,应该是 http://localhost:5000
  4. // 观察控制台输出 JSONP 的回调结果
  5. $ serve .

本文转载自微信公众号「全栈成长之路」,可以通过以下二维码关注。转载本文请联系全栈成长之路公众号。

当前名称:头条面试官:一文彻底搞懂JSONP
链接URL:http://www.hantingmc.com/qtweb/news31/516531.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联