第25题 JSONP的原理并用代码实现

基本原理:主要就是利用 script 标签的src属性没有跨域的限制,通过指向一个需要访问的地址,由服务端返回一个预先定义好的 Javascript 函数的调用,并且将服务器数据以该函数参数的形式传递过来,此方法需要前后端配合完成。

执行过程:

  • 前端定义一个解析函数(如: jsonpCallback = function (res) {})
  • 通过params的形式包装script标签的请求参数,并且声明执行函数(如cb=jsonpCallback)
  • 后端获取到前端声明的执行函数(jsonpCallback),并以带上参数且调用执行函数的方式传递给前端
  • 前端在script标签返回资源的时候就会去执行jsonpCallback并通过回调函数的方式拿到数据了。

缺点:

  • 只能进行GET请求

优点:

  • 兼容性好,在一些古老的浏览器中都可以运行

代码实现:

    <script>
        function JSONP({
            url,
            params = {},
            callbackKey = 'cb',
            callback
        }) {
            // 定义本地的唯一callbackId,若是没有的话则初始化为1
            JSONP.callbackId = JSONP.callbackId || 1;
            let callbackId = JSONP.callbackId;
            // 把要执行的回调加入到JSON对象中,避免污染window
            JSONP.callbacks = JSONP.callbacks || [];
            JSONP.callbacks[callbackId] = callback;
            // 把这个名称加入到参数中: 'cb=JSONP.callbacks[1]'
            params[callbackKey] = `JSONP.callbacks[${callbackId}]`;
            // 得到'id=1&cb=JSONP.callbacks[1]'
            const paramString = Object.keys(params).map(key => {
                return `${key}=${encodeURIComponent(params[key])}`
            }).join('&')
            // 创建 script 标签
            const script = document.createElement('script');
            script.setAttribute('src', `${url}?${paramString}`);
            document.body.appendChild(script);
            // id自增,保证唯一
            JSONP.callbackId++;
    
        }
        JSONP({
            url: 'http://localhost:8080/api/jsonps',
            params: {
                a: '2&b=3',
                b: '4'
            },
            callbackKey: 'cb',
            callback (res) {
                console.log(res)
            }
        })
        JSONP({
            url: 'http://localhost:8080/api/jsonp',
            params: {
                id: 1
            },
            callbackKey: 'cb',
            callback (res) {
                console.log(res)
            }
        })
    </script>
Last Updated:
Contributors: leeguooooo