使用 JSONP 解决同源限制问题

JSONPJSON with Padding的缩写,它不属于Ajax请求,但它可以模拟Ajax请求。

1. JSONP 跨域原理

  1. 浏览器的同源策略把跨域请求都禁止了
  2. html的<script>标签,<img>标签,<iframe>标签,可以请求第三方的资源(不受同源策略影响
  3. 由此可以用<script>标签引入jsonp文件,然后通过一系列JS操作获取数据

2. JSONP 实现跨域步骤

  1. 不同源的服务器端请求地址写在<script>标签的src属性中
<script src="www.example.com"></script>
  1. 服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数
const data = 'fn({name: "张三", age: "20"})';
res.send(data);
  1. 在客户端全局作用域下定义函数fn(),在fn()函数内部对服务器端返回的数据进行处理
function fn(data) {
    console.log(data);
}

3. JSONP 跨域举例

客户端:
JSONP.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <button id="btn">点击发送请求</button>
    <script>
        function fn(data) {
            console.log('客户端的fn函数被调用了')
            console.log(data);
        }
    </script>
    <script>
        // 获取按钮
        var btn = document.getElementById('btn');
        // 为按钮添加点击事件
        btn.onclick = function() {
            // 创建script标签
            var script = document.createElement('script');
            // 设置src属性
            script.src = 'http://localhost:3001/better?callback=fn';
            // 将script标签追加到页面中
            document.body.appendChild(script);
            // 为script标签添加onload事件,加载完毕后会触发
            script.onload = function() {
                // 将body中的script标签删除掉
                document.body.removeChild(script);
            }
        }
    </script>
</body>

</html>

服务器端:app1.js(3000端口)、app2.js(3001端口)
其中app2.js的代码:

// 引入express框架
const express = require('express');
// 创建web服务器
const app = express();

app.get('/better', (req, res) => {
    // 接收客户端传递过来的函数的名称
    const fnName = req.query.callback;
    // 将函数名称对应的函数调用代码返回给客户端
    const result = fnName + '({name: "Jack"})';
    res.send(result);
});

// 监听3001端口
app.listen(3001);
// 控制台提示输出
console.log('服务器2启动成功');

实现步骤及效果:

  1. 启动app1.jsapp2.js
  2. 浏览器地址栏输入:http://localhost:3000/JSONP.html
  3. 点击按钮
    在这里插入图片描述
    在这里插入图片描述
    返回了客户端传来的数据,实现了跨域。

此案例进行了JSONP的代码优化:

  1. 客户端需要将函数名称传递到服务器端。这样客户端改函数名称的时候,服务器端无需更改函数名称。
  2. <script>请求的发送变成动态请求。点击按钮需要请求时,才动态添加<script>标签,接收到数据之后就把<script>标签删除。避免了多次请求出现<script>标签冗余的情况。

进一步优化:
使用res.jsonp()方法,即可完成服务器端的所有功能。
app2.js

// 引入express框架
const express = require('express');
// 创建web服务器
const app = express();

app.get('/better', (req, res) => {
    // 接收客户端传递过来的函数的名称
    // const fnName = req.query.callback;
    // 将函数名称对应的函数调用代码返回给客户端
    // const result = fnName + '({name: "Jack"})';
    // res.send(result);

    // jsonp接受客户端传递的参数,将其转化为字符串,再拼接起来
    res.jsonp({ name: 'Jack', age: 20 });
});

// 监听端口
app.listen(3001);
// 控制台提示输出
console.log('服务器2启动成功');

在这里插入图片描述
完成了同样的跨域效果,客户端改函数名称的时候,服务器端无需更改函数名称。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火星飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值