封装-Jsonp

    技术2022-07-10  139

    封装-Jsonp

    Jsonpjsonp是什么?为什么使用jsonp?原理---jsonp的通俗讲解案例---使用script的src获取跨域数据 封装Jsonp案例---获取qq.com中的城市信息与天气信息

    Jsonp

    jsonp是什么?

    通过script标签中的src属性没有同源限制的方法进行获取数据

    即通过script标签来跨域获取数据,名为JSON with Padding, 或者就叫JSONP。JSONP的原理很简单,但需要服务器端给予相应配合。 大致来说,JSONP的实现思路就是在客户端编程时作好使用JSON数据的准备,然后再通过圆括号将这些数据括起来以创建一条有效的JavaScript语句(可能是一次有效的函数调用)。

    也就是说,客户端可以使用一个用于命名jsonp的查询参数来决定可以获取的数据。最简单的情况下,如果jsonp参数为空,则返回的数据就是被括在圆括号中的JSON

    为什么使用jsonp?

    浏览器安全模型规定,XMLHttpRequest、框架(frame)等只能在一个域中通信。 从安全角度考虑,这个规定很合理; 但是,也确实给分布式(面向服务、混搭等等本周提到的概念)Web开发带来了麻烦。

    本地代理: 需要一些硬件设施(没有服务器的客户端无法运行),并且带宽和潜伏时间也要加倍(远程服务器-代理服务器-客户端)。

    Flash: 远程主机中需要部署一个crossdomain.xml文件,而且,Flash作为一门专有技术,其前途尚不明朗;换句话说,开发人员很可能要学习一种目标不确定的编程语言。

    Script标签: 无法确切知道内容是否有效,没有标准的实现方法,又可能被认为是一种“安全风险”。

    原理—jsonp的通俗讲解

    使用script 的src属性没有同源限制,跨域名获取数据的一种方法

    案例—使用script的src获取跨域数据

    <script type="text/javascript"> // 定义一个jp函数 function jp(data) { console.log(data); } </script> <!-- 使用script 的src属性没有同源限制,跨域名获取数据的一种方法 --> <!-- 获取qq.com的天气信息,callback是返回的数据,jp是返回数据后调用的方法 --> <script src="https://apis.map.qq.com/ws/location/v1/ip?callback=jp&key=CAABZ-AVSAQ-RDR5L-GTBDJ-HLA4O-A5FDB&output=jsonp" ></script>

    封装Jsonp

    原理:使用script 的src属性没有同源限制,跨域名获取数据的一种方法动态的创建script标签,使用src属性来进行跨域获取数据其中使用有Promise,异步 // jsonp 利用script的src属性没有同源限制,跨域名获取数据的一种方法 // 后端返回的数据格式是,方法名(数据) // url 最重要 callback名称 jp 是callback的值 function jsonp(url,option={}) { // 默认回调函数参数名 callback var jp = option.jp||"callback"; // 默认回调函数参数值 var callback = option.callback||"jp"; return new Promise((resolve,reject) => { // 查看url是否有jp 没有还要加上 if(url.indexOf(jp)==-1){ url += "&"+jp+"="+callback; } // 如果有获取这已经加上了callback=值,获取callback的值 var p1 = url.indexOf(option.jp); // 获取到callback的位置 var p2 = url.indexOf("&",p1); // 从p1的位置开始查找符号"&" // 如果查找不到设置的p2位置, p2 == -1 ? p2 = url.lenght; // 就在url的末尾加, callback = url.slice(p1+jp.length+1,p2); // 动态的创建callback方法 window[callback]=function(data){ // 删除 document.head.removeChild(script); resolve(data); } // 动态创建script标签 let script = document.createElement("script"); // 将需要获取的数据的地址赋值给script 中的src属性,跳过浏览器的同源策略 script.src = url; // 将script标签追加到head中 document.head.append(script); // script加载失败 script.onerror = function(e){ // 动态删除script document.head.removeChild(script); reject(e)} }) }

    案例—获取qq.com中的城市信息与天气信息

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <p id="city" ></p> <img src="" id="img" alt=""> <p id="weather"></p> </body> <script type="text/javascript"> // jsonp 利用script的src属性没有同源限制,跨域名获取数据的一种方法 // 后端返回的数据格式是,方法名(数据) // url 最重要 callback名称 jp 是callback的值 function jsonp(url,option={}) { // 默认回调函数参数名 callback var jp = option.jp||"callback"; // 默认回调函数参数值 var callback = option.callback||"jp"; return new Promise((resolve,reject) => { // 查看url是否有jp 没有还要加上 if(url.indexOf(jp)==-1){ url += "&"+jp+"="+callback; } // 如果有获取这已经加上了callback=值,获取callback的值 var p1 = url.indexOf(jp); // 获取到callback的位置 var p2 = url.indexOf("&",p1); // 从p1的位置开始查找符号"&" // 如果查找不到设置的p2位置, p2 == -1 ? p2 = url.lenght : ''; // 就在url的末尾加, callback = url.slice(p1+jp.length+1,p2); // 动态的创建callback方法 window[callback]=function(data){ // 删除 document.head.removeChild(script); resolve(data); } // 动态创建script标签 let script = document.createElement("script"); // 将需要获取的数据的地址赋值给script 中的src属性,跳过浏览器的同源策略 script.src = url; // 将script标签追加到head中 document.head.append(script); // script加载失败 script.onerror = function(e){ // 动态删除script document.head.removeChild(script); reject(e) } }) } var url1 = "https://apis.map.qq.com/ws/location/v1/ip?key=CAABZ-AVSAQ-RDR5L-GTBDJ-HLA4O-A5FDB&output=jsonp"; var url2 = "https://wis.qq.com/weather/common?weather_type=observe|forecast_24h|air&source=pc&callback=jp"; // 获取地址 jsonp(url1) .then(res=>{ url2 = url2+`&province=${res.result.ad_info.province}&city=${res.result.ad_info.city}`; city.innerHTML=res.result.ad_info.city; return jsonp(url2); //获取天气 }) .then(res=>{ weather.innerHTML=res.data.observe.degree+"℃"; // 动态的天气图片 img.src="https://mat1.gtimg.com/pingjs/ext2020/qqindex2018/dist/img/weather/"+res.data.observe.weather_code+".svg"; }) </script> </html>
    Processed: 0.010, SQL: 9