Day 1 Jsonp 跨域解决方案分析

背景

As we all know,浏览器同源策略会将非同源请求(跨域)抛弃,而许多时候我们可能併未将前端资源与服务端服务放在一个服务器,此时就需要一个跨域的手段了。

基于此,针对同源策略,衍生了一种跨域的方法Jsonp。

Jsonp简单讲,即利用了script标签不受浏览器同源策略影响的特性,从而利用script想服务端跨域请求的方式。

原理解析

封装一个Jsonp函数,Promise化

// jsonp.tstype JsonpOptions<T extends Record<string, any>> = {    url: string,    timeout: number,    data: T,    cbKey?: string};interface JsonpRes {    code: 0 | -1,    data: any,    msg: string}export default function createJsonp<T extends Record<string, any>> (options: JsonpOptions<T>): Promise<JsonpRes> {    return new Promise((resolve, reject) => {        // 第一次请求,初始化随机数        if (!jsonpNumber) {            jsonpNumber = 1;        } else {            jsonpNumber++; // 拼接到callbackFn上,以防止多个jsonp请求时错误使用同一个callback        }        // callback接收函数名        const jsonpReceiverFnName = 'jsonpReceiver' + jsonpNumber;        const {            url,            timeout,            data,            cbKey = 'callback'        } = options;        let script: HTMLScriptElement; // 将被插入DOM的script标签        // 设置超时定时器        let timeoutTimer = setTimeout(() => {            reject({                code: -1,                data: null,                msg: '请求超时'            });            clear();         }, timeout);        // 清除上一次请求存的变量/定时器        function clear () {            window[jsonpReceiverFnName] = null; // 删除callbackFn            clearTimeout(timeoutTimer); // 清除定时器            script.parentNode?.removeChild(script); // 移除当前jsonp的script        }        window[jsonpReceiverFnName] = (res) => {            resolve({                code: 0,                data: res,                msg: '请求成功'            }); // 将数据返回到            clear(); // 请求成功后,清理本次jsonp带来的“副作用”        }        // 创建JSONP请求标签,发出请求        let params = ''; // 仅支持get请求,故只有query参数        // 遍歴data,拼接参数        for (let key in data) {            if (data.hasOwnProperty(key)) {                params += `&${key}=${data[key]}`;            }        }        params = params.substring(1); // 移除第一个 &        script = document.createElement('script');        script.src = `${url}?${params}&${cbKey}=${jsonpReceiverFnName}`; // 拼接请求url        document.body.appendChild(script); // 插入body,正式发出jsonp请求    });};

调用

// 调用jsonp函数<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <script src="./jsonp.js"></script></head><body>    <script>        async function testJsonp() {            try {                const res = await createJsonp({                    url: 'https://x.x.x.x/testjsonp',                    timeout: 15000,                    data: {                        id: '00145x',                        level: 2                    }                });                !res.code && console.log(res.data)            } catch (rejectRes) {                rejectRes.code && console.log(rejectRes?.msg)            }        }        testJsonp();    </script></body></html>

That's all. Shuan Q


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章