前端 JSONP 原理及 Node 模拟 JSONP

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/')
})

4、成功后,页面 Dom 结构效果

image.png

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)
  }
})
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容。 本文完整的源代码...
    捞白杨阅读 309评论 0 0
  • 1、JS的数据类型只有浮点型,没有整型。null,underfined,boolean,number,string...
    6e5e50574d74阅读 2,312评论 2 1
  • 什么是跨域? 2.) 资源嵌入:、、、等dom标签,还有样式中background:url()、@font-fac...
    电影里的梦i阅读 2,402评论 0 5
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 126,591评论 2 7
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,139评论 0 4