【JavaScript39】jsonp

发布时间 2023-08-12 22:03:31作者: Tony_xiao

为了解决浏览器跨域问题. ajax提供了jsonp请求.

  • 在网页端如果见到了服务器返回的数据是:xxxxxxxxxxdjsfkldasjfkldasjklfjadsklfjasdlkj({json数据})
  • 在Preview里面可以像看到json一样去调试,這就是jsonp。 这东西依然是ajax.
  • jsonp的逻辑是. 在发送请求的时候. 带上一个callback字符串. 该字符串自动发送给服务器. 服务器返回数据的时候. 会带上该callback字符串. 我们在抓包中看到的就是这样的效果:

跨域演示

  • 搭建一个服务器
  • 在服务器外面,新增一个index.html文件
  • 如果当前html被右键run..pycharm会自动帮你开一个服务器.在这个服务器里. 有这个html以及该html所在的文件夹
from flask import Flask, render_template, request, make_response
# pip install flask_cors

app = Flask(__name__)

# http://127.0.0.1:5000/
@app.route("/")
def func0():
    news = "这是一个完整的html页面"
    return render_template("index.html",
                           xwl_de_news=news,)

@app.route("/new_ajax",methods=["GET", "POST"])
def funccccc():
    uname = request.args.get('uname')
    age = request.args.get('age')

    print(uname, age)
    return "返回的数据"
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 注意, 浏览器访问静态资源, 没有跨域问题. -->
    <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
    我是一个完整的html
    <button id="bbb">我是按钮</button>
    <script>

        // 如果当前html被右键run..pycharm会自动帮你开一个服务器.
        // 在这个服务器里. 有这个html以及该html所在的文件夹
        //
        $("#bbb").click(function(){
            // // 发的get请求
            $.ajax({ // jquery封装好的ajax请求.
                // 发ajax的一些配置信息
                // http://localhost:63342/new_ajax?uname=xwl&age=18
                url: "http://127.0.0.1:5000/new_ajax?uname=xwl&age=18",
                method: "get",
                // 请求成功后. 你要做什么
                success: function(data){ // data表示返回的内容
                    console.log(data);
                }
            });
            // 1.浏览器不允许XMLHttpRequest跨域产生
            // 2.img, script, 没有跨域问题的.
        });
    </script>

</body>
</html>

  • 如何解决跨域问题
//解决方案用的是在响应头里增加Access-Control-Allow-Origin
resp.headers['Access-Control-Allow-Origin'] = "*"

借助javascript发送ajax请求,这种方式就叫jsonp

  • 服务器端
from flask import Flask, render_template, request, make_response

app = Flask(__name__)

@app.route("/")
def func0():
    news = "这是一个完整的html页面"
    return render_template("index.html",
                           qiaofu_de_news=news,)

# jsonp的逻辑
@app.route("/new_ajax",methods=["GET", "POST"])
def funccccc():
    cb = request.args.get("cb")
    uname = request.args.get('uname')
    age = request.args.get('age')
    print(uname, age)

    resp = make_response(f"{cb}('哈哈');")  # 返回的是js代码
    return resp
  • 前端代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 注意, 浏览器访问静态资源, 没有跨域问题. -->
    <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
    我是一个完整的html
<!--    <img src="https://img2.baidu.com/it/u=288534754,2483854920&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=726">-->
    <button id="bbb">我是按钮</button>
    <script>

        $("#bbb").click(function(){
            // 借助script完成ajax请求
            let url = "http://127.0.0.1:5000/new_ajax?uname=xwl&age=18";
            jsonp(url, function(data){
                console.log("返回的参数是", data);
            });
        });

        function jsonp(url, fn){
            // 随机生成一个名字
            var n = Date.now();
            var cb = "m"+n; // m1651111322245

            // 发请求之前定义一个函数
            window[cb] = fn;
            url += "&cb="+cb;
            var script = document.createElement("script"); // 创建一个script标签
            script.setAttribute("src", url);    // 设置属性, src,
            document.head.appendChild(script); // 把script标签添加到head标签中. 此时会自动发请求到url
            // 上述逻辑返回的数据, 被当成了js代码给运行了.
        }

        // 总结. 上述逻辑是借助于script标签来发送请求
        // 传统的xhr发请求是有跨域问题的.
        // 该方法是没有跨域问题的.
        // 把请求伪装成了静态资源的访问.
        // 特点1: 请求的参数里会有一个类似随机值字样的东西. 该参数是服务器返回数据里的`函数调用`
        // 特点2: 服务器返回的是js代码....
        // 特点3: 返回的js代码中 函数调用对我们来说是没用的, 我们要的是数据. 数据在参数上.
        // kljfdklsjkalfdajsklfjdsa(数据)

    </script>
</body>
</html>