一个失常的申请: 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=paddingpadding({  "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 仓库: https://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 .

本文收录于 GitHub 日问: DailyQuestion,内含大厂内推机会、面经大全及若干面试题,每天学习五分钟,一年进入大厂中。

  • 大厂面经大全
  • 大厂内推