JSONP的历史方案和实现原理

1. JSONP的实现原理

JSONP是通过动态创建script实现的。

请求方:frank.com 的前端程序员(浏览器)。

响应方:jack.com 的后端程序员(服务器)。

(1).请求方创建 script, src 指向响应方,同时传入一个查询参数 ?calbackName=yyy。

(2).响应方根据查询参数callbackName,构造性如:

    (一).yyy.call(undefined,'你要的数据')

    (二).yyy('你要的数据')

这样的响应。

(3).浏览器接收到响应,就会执行 yyy.call(undefined,'你要的数据')。

(4).那么请求方就知道了他要的数据。

整个过程就是JSONP的实现过程。

2. JSONP相关历史方案

例子:用数据库做加法

一个简易的server服务器

    代码:版本1

做一个点击button,价格减1的demo,没有和数据库进行交互

      代码:没有数据库的版本

2.1 利用form请求数据

增加数据库文件db.txt,与数据库进行交互

    修改html,利用form表单post方法发送数据,请求路径 /pay,方法 post,点击提交按钮,金额减一。

    新建db.txt,内容为100

    修改db.txt,增加端口'/pay',使得网页每次请求,金额减一。

     效果,点击提交后,点击后退按钮,刷新页面,金额是会减一。

    代码:添加数据库的版本

修改server.js,添加随机数,让求情可能成功可能失败。

    代码:随机请求的版本

    细节:每次点击提交form,页面都会刷新,如何优化?

    古老的方法:利用iframe代替页面刷新

修改index.html,让form的target指向iframe

     代码:利用iframe代替页面刷新

    如何不用iframe?

2.2 利用 image发送请求

不用form创建请求,而利用image来发请求

    创建image,放在内存中,浏览器发现就会立即请求img的source

    修改index.html, 在script标签中创建img元素,并让img.src='./pay',添加img.onload和onerror,根据状态码显示失败或成功

    修改server.js, 删除if条件必须是post,给响应添加状态码,成功响应200,失败响应400

    结果:只能显示失败,重要的的是理解利用image来发请求的思路

    代码:利用image来发请求

解决bug,我们并没有如真正的图片所以失败了,只需要给服务器一张真的图片即可(1X1的空白像素)

     这里用随意一张图片代替

    修改server.js,‘./pay’接口的if成功区块

response.setHeader('Content-Type','img/jpg')
response.write(fs.readFileSync('./dog.jpg'))

    代码:修改img发送请求的bug

    代码:利用winodw.reload()请求成功后自动刷新

修改index.html,打钱成功后,添加window.location.reload()实现请求成功后的自动刷新但这样会重新加载页面,我们需要的是页面局部更新

    修改index.html,删除window.locaiton.reload(),添加amount.innerText = amount.innerText - 1

这样我们在服务器数据更改的同时,页面上显示的数据也实现了更新。

    代码:页面局部更新

2.3 利用script发送请求

利用script发请求

    修改index.html,创建script,script.src等于接口,并且需要将创建的script插入到body中,不然不起作用。

    修改server.js的数据传输类型为 application/javascript

    代码:利用script发请求

每次我们点击提交时,都会新创建一个script标签插入到页面中

    修改server.js,pay接口,成功时写入‘我是pay’

由于页面中出现了script标签,浏览器就会将这个script执行掉,而它里面的内容就是alert('我是pay'),执行完之后再去调用onload事件。

    代码:插入页面的script标签会被执行

修改server.js,去掉响应失败,全部响应成功,如果成功,则弹出对话框‘我是pay’

    代码:先执行响应内容,然后调用onload

    删除onload,通过response.write对页面数字进行更改,形成比较简洁的方案

    代码:利用response.write()

每次提交都会添加script标签,我们可以删掉

修改index.html,
添加script.onload = function(e) {
                e.currentTarget.remove()
            }

    代码:删掉动态添加的script标签

2.4 SRJ

这个方案名:SRJ Server rendered javascript 服务器返回的javascirpt,在ajax出来以前,程序员想出来的,无刷新局部更新页面内容的方案。

2.5 请求另一个网站的script

请求另一个网站的script

两个网站通过SRJ相互访问。

    修改hosts,命令行 vi /etc/hosts ,让frank.com和jack.com等价于127.0.0.1

    修改hosts参考链接https://jingyan.baidu.com/article/b907e627d86be046e6891c41.html

    在最后面添加

    127.0.0.1 frank.com

    127.0.0.1 jack.com

    监听8001端口的网站 命令行 node server.js 8001

    监听8002端口的网站 命令行 node server.js 8002

打开窗口通过,打开frank.com:8001和jack.com:8002,它们是两个不同的网站

     修改index.html,script.src = 'http://jack.com:8002/pay'

    点击8001的打钱按钮,服务器返回的是8002对应服务器的数据。

    代码:两个网站SRJ相互访问

这个方案的缺点,后端对前端的了解太深入了,耦合程度太高,所以需要解耦

修改index.html
    window.xxx = function(result) {
                if(result === 'success') {
                    amount.innerText = amount.innerText - 1
                } else {
                }
            }
    script.src = 'http://jack.com:8002/pay?callbackName=xxx'

修改server.js

${query.callbackName}.call(undefined,'success') 这样来解耦,这样后端不许要知道前端的细节,只需要给结果就行了。

script不受域名限制,ajax受域名限制

    代码:前后端解耦

2.6 JSONP的由来

JSONP的由来,{}左边加左padding,右边叫右padding,简称JSONP。。。。。

也就是JSON+padding=JSONP

如果是String的话,也可以是String + padding = StringP

    代码:JSONP的由来

3. JSONP

JSONP

请求方:frank.com 的前端程序员(浏览器)。

响应方:jack.com 的后端程序员(服务器)。

(1).请求方创建 script, src 指向响应方,同时传入一个查询参数 ?calbackName=yyy。

(2).响应方根据查询参数callbackName,构造性如:

    (一).yyy.call(undefined,'你要的数据')

    (二).yyy('你要的数据')

这样的响应。

(3).浏览器接收到响应,就会执行 yyy.call(undefined,'你要的数据')。

(4).那么请求方就知道了他要的数据。

这就是JSONP

3.1 约定

约定:

1.callbackName -> calllback

2.yyy -> 随机数 frank18375912375()



一个符合约定的JSONP

随机数每次调用完,都及时销毁,不占用全局变量

    代码:一个符合约定的JSONP

3.2 使用jquery实现JSONP

只需要确定url的值,dataType的值是jsopn,响应成功后做什么;不用管后台如何调用。

注意:JSONP不是ajax,只是jquery把JSONP归为ajax的方法里面去了。

button.addEventListener('click', (e)=>{
            $.ajax({
                url: "http://jack.com:8002/pay",
                dataType: "jsonp",
                success: function(response) {
                    if(response === 'success') {
                        amount.innerText = amount.innerText - 1
                    }
                }
            }) 
})

这个方法和ajax没关系,它只是简化了JSONP的整个过程

    代码:jquery实现JSONP

3.3 JSOPN误导

1.名字会误导你,让你以为它和JSON有关系

2.jquery会误导你,让你以为它和ajax有关系

4. 面试题

4.1 什么是 JSONP?

JSONP
请求方:frank.com 的前端程序员(浏览器)。

响应方:jack.com 的后端程序员(服务器)。

(1).请求方创建 script, src 指向响应方,同时传入一个查询参数 ?calbackName=yyy。

(2).响应方根据查询参数callbackName,构造性如:

    (一).yyy.call(undefined,'你要的数据')

    (二).yyy('你要的数据')

这样的响应。

(3).浏览器接收到响应,就会执行 yyy.call(undefined,'你要的数据')。

(4).那么请求方就知道了他要的数据。

这就是 JSONP

约定:

    1. callbackName -> callback

    2. yyy -> 随机数 frank12312312312321325()

    3. jQuery 用法

 $.ajax({
 url: "http://jack.com:8002/pay",
 dataType: "jsonp",
 success: function( response ) {
     if(response === 'success'){
     amount.innerText = amount.innerText - 1
     }
 }
 })

4.2 请问 JSONP为什么不支持POST请求(99%)

因为JSONP是通过动态创建script实现的,而动态创建script的时候只能用get没有办法用post。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容

  • JSONP 问:什么是JSONP? 1. 问题引入 在日常开发中,前端程序员想要从后端请求一些数据,是如何操作的呢...
    黄同学2019阅读 415评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,559评论 18 139
  • 页面数据交互的发展过程 付款是我们日常中常见的一种金钱交易,用户在页面中点击付款按钮,网页提交请求给服务器,服务器...
    鹧鸪少阅读 907评论 0 0
  • 最近追了一部三生三世的剧,感觉自己好像比较喜欢虐心的部分,而到了两人恩爱,互诉衷肠的部分呢,就觉得好假。 为什...
    luccy99阅读 230评论 0 0
  • 以前看过一部电影,叫做《陪安东尼度过漫长岁月》,男主安东尼陪着一直暗恋的女生到海里寻找一条鲸鱼,想要收集它发出的声...
    慢性患者阅读 3,883评论 0 0