前端 JSONP 原理及 Node 模拟 JSONP
2021-08-01 本文已影响0人
弹力盒
1、关于 JSONP 请求的注意项
-
a、JSONP 请求只支持 GET 形式
-
b、JSONP 请求返回的是一个自定义函数,函数名由 callback 传递
2、JSONP 实现原理(前端)
/**
* JSONP 前端原理(具体分为以下四步)
* JSONP 请求只支持 GET 形式
*/
function getJSONP () {
/**
* 第一步
* 创建一个 script 标签
*/
const script = document.createElement('script')
/**
* 第二步
* 绑定 script 标签 src 属性
* 并设置回调函数名(这里为 getData)
*/
const url = 'http://127.0.0.1:15000/jsonp?callback=getData'
script.setAttribute('src', url)
/**
* 第三步
* 全局环境下设置回调函数
* !!! 一定要在全局环境下,getJSONP 函数作用域内不行
*/
window.getData = function (data) {
console.log(data)
}
// 第四步,在 head 标签下添加上述的 script 标签
document.getElementsByTagName('head')[0].appendChild(script)
}
// 开始请求
getJSONP()
3、JSONP 实现原理(Node + Express)
const express = require('express')
const app = express()
app.use(express.static('./'))
// 首页展示
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
/**
* jsonp 请求 express 写法
* jsonp 仅支持 GET 请求,由于 script 标签的限制
*/
app.get('/jsonp', (req, res) => {
res.jsonp({ name: 'hehe' })
})
app.listen(15000, () => {
console.log('server is running at localhost:15000/')
})
image.png4、成功后,页面 Dom 结构效果
5、简单封装
/**
* 简单封装
* 采用箭头函数形式,声明的 getData 里面的 this => window
* @param { jsonp 接受属性 } options
*/
const getData = (options) => {
// 设置 options 的默认属性
const defaultOptions = {
callback: 'callback',
data: {},
success: function (data) { }
}
// 覆盖默认 options 属性
options = Object.assign(defaultOptions, options)
// 设置全局回调函数
window[options.callback] = function (data) {
options.success(data)
}
// 创建 script 标签,并设置其 src 属性
const script = document.createElement('script')
const url = `
http://127.0.0.1:15000/jsonp?callback=
${options.callback}${formatParams(options.data)}
`
script.setAttribute('src', url)
// 将 script 标签绑定到 body 上面
document.getElementsByTagName('head')[0].appendChild(script)
}
// 格式化 jsonp 请求参数
const formatParams = (params = {}) => {
let result = ''
for (const i of Object.entries(params)) {
result += `&${i[0]}=${i[1]}`
}
return result
}
getData({
callback: 'hahaha',
data: { param1: 'param1' },
success: function (data) {
console.log(data)
}
})