基于express和vue3实现jsonp请求

最近回顾一下jsonp的请求方式,jsonp是一种比较老的前端跨域请求的方式,原理就是利用浏览器<script> <img>等标签src属性不受跨域限制,在script标签中写入方法获取接口数据,此跨域方案兼容性非常好,即便以前的老IE浏览器都可兼容。

第一步创建一个vue3项目,在src下创建一个jsonpSever.ts或js文件,文件内容如下

需要下载插件

npm install express

npm i body-parse

如果创建的是ts文件,建议下载 nodemon 热更新ts文件避免每次修改完ts文件手动重启问题

npm install --save-dev nodemon

此外ts文件还需要下载一个ts-node执行ts文件全局安装即可

npm install -g ts-node

在package.json添加一个执行命令实际根据知己的路径填写

"jsonp:dev": "nodemon src/jsonpSever/index.ts"

const express = require('express');
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json());

// 跨域配置
app.all('*', function (err: any, req: any, res: any, next: any) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header(
    'Access-Control-Allow-Headers',
    'Content-Type,Content-Length,Authorization,Origin,Accept,X-Requested-With'
  );
  res.setHeader('Content-type', 'application/json;charset=utf-8');
  if (err.name === 'UnauthorizedError') res.status(401).send('invalid token...');
  // ### next() 代表要此中间件执行完毕后执行下一个中间件, 一般在中间件里面书写, 其他地方不要用
  next();
});

app.get('/bpmsever',  (req: any, res: any) => {
  // 这一步JSONP必备
  const _callback = req.query.callback
  // 服务端获取的callback就是我们定义的funapi
  const  response = {
    code: 200,
    message: 'success',
    data: {
      name: '测试'
    }
  }
  if (_callback){
    // 这两步设置发送也是NODE.JS发送JSONP必备
    res.type('text/javascript')
    res.send(_callback + `(${ JSON.stringify(response) })`)
  } else {
    res.json(response)
  }
})

const port = 3030

app.listen(port, () => {
  console.log(`server run at:\n- Local: http://localhost:${port}/`);
})

第二步封装api写入方法获取接口数据

/**
 * @param {api} 请求路径
 * @param {fnName} 获取数据的回调函数
 * @param {f} 定义的获取数据的函数名
 * @returns {Promise}
 */
function creatJsonpReq(api: string, fnName: Function, f: string) {
  const body = document.getElementsByTagName('body')[0]
  const javaScriptElApi = document.createElement('script')
  const javaScriptElFn = document.createElement('script')
  javaScriptElApi.type = 'text/javascript'
  javaScriptElFn.type = 'text/javascript'
  javaScriptElApi.src = api + '?' + `callback=${f}`
  // javaScriptElFn.defer = true
  const fn = fnName.toString() // append 允许传递参数 string | Node 需要转成字符串
  javaScriptElFn.append(fn)
  body?.append(javaScriptElApi)
  body?.append(javaScriptElFn)
  return new Promise((reslove) => {
    fnName().then((res: any) => { reslove(res) })
  })
}

第三步使用封装的方法

funcapi在vite-env.d.ts声明下,解决报window属性问题

interface Window {
  funcapi?: Function
}
<script setup lang="ts">
import { onMounted } from 'vue'
import { creatJsonpReq } from '@/utils/index'

function jsonp(){
  return new Promise((resolve, reject) => {
    //在全局定义一个 doSomething 的函数
    window.funcapi = function(data: any) { resolve(data) }
  })
}
onMounted(async () => {
  const data = await creatJsonpReq('http://localhost:3030/bpmsever', jsonp, 'funcapi')
  console.log(data, 'data')
})
</script>

<style scoped>

</style>

执行"jsonp:dev": "nodemon src/jsonpSever/index.ts"命令后

再开一个终端执行vue文件最终可打印出data的值

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值