最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入浅出实现最简 JSONP

    正文概述 掘金(shanyue)   2020-12-18   357

    一个正常的请求: JSON

    正常发请求时,curl 示例:

    $ curl https://shanyue.tech/api/user?id=100
    
    {
      "id": 100,
      "name": "shanyue",
      "wechat": "xxxxx",
      "phone": "183xxxxxxxx"
    }
    

    使用 fetch 发送请求,示例:

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

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

    handleData(data)
    

    一个 JSONP 请求

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

    curl 示例

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

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

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

    window.padding = handleData
    

    这里实现一个 jsonp 函数

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

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

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

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

    代码附录

    完整代码可见山月博客的 github 仓库: github.com/shfshanyue/…

    JSONP 实现完整代码:

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

    JSONP 服务端适配相关代码:

    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)
    
      const data = { name: 'shanyue', id: params.id }
    
      if (params.callback) {
        str = `${params.callback}(${JSON.stringify(data)})`
        res.end(str)
      } else {
        res.end()
      }
    
    })
    
    server.listen(10010, () => console.log('Done'))
    

    JSONP 页面调用相关代码

    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title></title>
    </head>
    <body>
      <script src="./index.js" type="text/javascript"></script>
      <script type="text/javascript">
      jsonp({
        url: 'http://localhost:10010',
        params: { id: 10000 },
        onData (data) {
          console.log('Data:', data)
        }
      })
      </script>
    </body>
    </html>
    

    JSONP 实现代码示例演示

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

    文件结构

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

    快速演示

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

    起源地下载网 » 深入浅出实现最简 JSONP

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元