2021-4-9 前端达人
jsonp
的核心原理是利用script
标签没有同源限制的方式,可以发送跨域的get
请求(只能发送get
请求)。script
标签中的src
属性将请求参数和当前请求的回调函数名拼接在链接上。最终由服务端接收到请求之后拼接成前端可执行的字符串的形式返回。这个结果字符串最终会在前端的script标签中解析并执行。
利用<script>
标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的JSON
数据。JSONP
请求一定需要对方的服务器做支持才可以。
JSONP
和AJAX
对比: JSONP
和AJAX
相同,都是客户端向服务端发送请求,从服务端获取数据的方式。但AJAX
属于同源策略,JSONP
属于非同源策略(跨域请求)。
JSONP
优缺点: JSONP
优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅仅支持get
方法具有局限性,不安全,可能会遭受XSS
攻击。
jsonp
回调函数的名称callbackName
拼接到src
上
script
标签,设置它的src
属性
callbackName
回调函数,等待script
标签请求结束,并调用
/**
* jsonp获取请求数据
* @param {object}options
*/ function jsonp(options) { // console.log(options); // 1. 产生不同的函数名(函数名随机) let callBackName = 'itLike' + Math.random().toString().substr(2)+Math.random().toString().substr(2); // console.log(callBackName); // 2. 产生一个全局函数 window[callBackName] = function (params) { // console.log(params); // console.log(options.success); if(params !== null){ options.success(params); }else{ options.failure(params); } // 2.1 删除当前脚本标签 scriptE.remove(); // 2.2 将创建的全局函数设为null window[callBackName] = null; }; // 3. 取出url地址 let jsonpUrl; if(options.data !== undefined){ jsonpUrl = options.url + '?' + options.data + '&callBack=' + callBackName; }else { jsonpUrl = options.url + '?callBack=' + callBackName; } // console.log(jsonpUrl); // 4. 创建script标签 let scriptE = document.createElement('script'); scriptE.src = jsonpUrl; document.body.appendChild(scriptE); }
服务端(express)
router.get('/api/v1', function(req, res, next) { res.json({ 'name': '前端收割机', 'address': '广东', 'intro': '前端技术交流公众号' }); });
调用jsonp
btn.addEventListener('click', ()=>{ jsonp({ url: 'http://localhost:3000/api/v1', data: 'name=前端收割机&age=20', success: function (data) { console.log(data); }, failure:function(data){ console.log(数据请求失败); } }); });
show
)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data
)
<script src=>
标签 ,把那个跨域的API
数据接口地址,赋值给script
的src
, 还要在这个地址中向服务器传递该函数名(可以通过问号传参?callback=show
)。
show
,它准备好的数据是 show('前端收割机')
。
HTTP
协议返回给客户端,客户端再调用执行之前声明的回调函数(show
),对返回的数据进行操作。
/**
* jsonp获取请求数据
* @param {string}url
* @param {object}params
* @param {function}callback
*/ function jsonp({ url, params, callback }) { return new Promise((resolve, reject) => { let script = document.createElement('script'); params = JSON.parse(JSON.stringify(params)); let arrs = []; for (let key in params) { arrs.push(`${key}=${params[key]}`); } arrs.push(`callback=${callback}`); script.src = `${url}?${arrs.join('&')}`; document.body.appendChild(script); window[callback] = function (data) { resolve(data); document.body.removeChild(script); } }) }
服务器(express
)
// 后端响应 // 这里用到了 express var express = require('express'); var router = express.Router(); var app = express(); router.get('/say',function(req,res,next) { //要响应回去的数据 let data = { username : 'zs', password : 123456 } let {wd , callback} = req.query; console.log(wd); console.log(callback); // 调用回调函数 , 并响应 res.end(`${callback}(${JSON.stringify(data)})`); }) app.use(router); app.listen(3000);
调用jsonp
// 前端调用 btn.addEventListener('click', ()=>{ jsonp({ url: 'http://localhost:3000/say', params: { wd: '前端收割机' }, callback: 'show' }).then(data => { console.log(data) }); });
基本原理:利用 script
标签的 src
没有跨域限制来完成实现。
优缺点:只能 GET
;兼容性好。
简单实现:通过 url, params, callback
来定义 JSONP()
方法的参数。
转自:csdn论坛 作者:imagine_tion
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com