查资料的解释: JSONP数据交互协议一般用于Ajax跨域请求。Ajax直接请求普通文件存在跨域无权限访问的问题,然而web页面上调用js文件则不受是否跨域的影响(凡是拥有src该属性的标签都有跨域的能力),于是通过web端跨域访问数据的时候,设法把数据装进js格式的文件里面。获取之后便可以在web端进一步进行处理。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一 个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了
jsonp的整个过程就类似于前端声明好一个函数,后端返回执行函数。执行函数参数中携带所需的数据
个人理解:即就是因为我们在数据交互的时候需要的数据是需要跨域的,但是我们常用的ajax又不支持跨域请求,所有jsonp诞生了,jsonp就是一种非正式的传输协议,即通过web页面在调用js时可以跨域这个特点,我们把我们需要的数据放在远程服务端的js格式的文件里,这样web端 就可以获取了,获取后如何处理数据就是web端的事情,即可以写一个函数来处理,在后端调用这个函数就可以了,但是这个方法一个难点就是因为请求的时候我们每次使用这个jsonp是需要调用的函数的名字是不一样的,即我们可以在让这个函数的名字动态生成,然后再把这个名字传入后端执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | function jsonp(option) { // 将用户通过对象命名空间传递进来的函数挂载到全局 var callbackName = 'itcast_' + Math.random().toString().substr(2) + Math.random().toString().substr(2) !window.callbacks && (window.callbacks = {}) window.callbacks[callbackName] = function (data) { option.success(data) // 这里才意味着可以删除 script 标签了 // 这里可以直接使用 script ,原因是下面的变量提升,而且等这里使用 script 的时候,下面的代码早就执行结束了 document.body.removeChild(script) } // 1. 解决 url 问题 // 2. 解决回调处理函数问题 option.url = option.url + '?callback=callbacks.' + callbackName //这里就是将动态生成的函数名通过URL路径传给后端(callbacks对象中的callbackName属性) //即因为jsonp只支持get方法,就需要把数据写入到url中 var script = document.createElement('script') script.src = option.url // 将 script 上到 DOM 中 document.body.appendChild(script) } 服务端: const express = require('express') const app = express() app.get('/', (req, res, next) => { console.log(`收到客户端请求了:${req.url}`) var data = JSON.stringify({ foo: 'bar', list: [1, 2, 3] }) setTimeout(function () { res.end(`${req.query.callback}(${data})`) }, 1000)//获取路径的callback中的函数名,然后执行此函数 }) app.listen(3000, () => { console.log('running...') }) |