前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基础 | 前端通信进阶(上)

基础 | 前端通信进阶(上)

作者头像
用户1097444
发布2022-06-29 15:29:14
6670
发布2022-06-29 15:29:14
举报
文章被收录于专栏:腾讯IMWeb前端团队

作者|jaychen

原文|https://segmentfault.com/a/1190000004682473

在几年前,天空一声巨响,ajax 闪亮登场. 前端宝宝们如获至宝~ 已经表单提交神马的, 真的太心累了. 有了ajax之后, 网页的性能可大幅提升,告别刷新,告别如水的流量. 不过,长江后浪推前浪,一代更比一代强. 由于ajax被同域限制着, 导致, 多服务器配置,云服务资源的存储 没办法充分利用. 所以,业界想到另外一种方法--JSONP. JSONP实际上和ajax没有半点关系,唯一相同的就是都是异步执行,而且JSONP完美解决了CD(cross domain)问题. 科技就是第一生产力, web发展so fast. 以前追求就是静态网页,显示信息而已。 现在,正朝着web2.0,webapp前进。 以前的单向交流 已经不能满足 需求了。 怎么办呢? 改呗~ 所以,紧接着SSE,websocket 诞生了. 至今为止, 前端通信方式算是告一段落。 这里我们将围绕上述的几种通信方式进行,简单的介绍. 以下是几个技术的顺序.

  • ajax
  • JSOP
  • SSE
  • websocket

ok~ 进入主题吧~

AJAX

相信这个应该不用过多的讲解了吧. 差不多就4步:

  • 创建xhr对象
  • 监听请求
  • 设置回调
  • 设置参数
  • 发送xhr
  • 获得数据执行回调

这里,我就直接上代码了.

这样差不多就完成了一个ajax的简单模型。当然,我们也可以使用jquery提供的$.ajax函数, 只是他里面做了更多的兼容性和功能性.

JSONP

JSONP 就是 JSON with Padding... 我真的不知道这个名字的含义到时有什么卵用...一开始在使用JSONP时, 就是使用jquery的$.ajax函数就可以了. 但,这造成了一个很不好的impression. 总是让我们以为,JSONP 和 ajax有什么关联似的. 而,事实上,他们两个是完全不同的机制. xhr原理大家已经很清楚了,就是完完全全的异步操作. 但JSONP的原理是什么呢?

JSONP原理

JSONP 其实是和< script> 标签 有很大的关系. JSONP最大的优势就是实现异步跨域的作用, 他到底是怎么做到的呢? 其实, JSONP就是利用script 的 src属性,实现跨域的功能.

talk is cheap, show the code

上面的写法有点不符合前端风味. 说明一下, 其实processJSON,其实就相当于一个回调函数而已. 在script--src里面的内容我们来瞧一瞧. 使用jsoncallback 来指定回调函数名字, 并且传入一些参数:

  • name = jimmy
  • age = 18

这就是前端发送JSONP的全部. 那应该怎么执行呢?或者说,返回的内容是什么呢? 很简单, 根据jsoncallback里面指定的函数名--processJSON. 在返回的js里面使用processJSON(data); 来执行. 服务器端返回的js内容.

然后,浏览器收到后,直接执行即可. 这里,我们来模拟一下服务器端盖怎样执行一个JSONP的函数.

ok~ 上面基本上就可以完成一个简单的JSONP函数执行。 当然,express 4.x 里面也有相关的JSONP 操作。 有兴趣的同学可以看一看.then, 我们可以模拟一下实在的JSONP请求.上面是直接将script 写死在html内部, 这样造成的结果可能会阻塞页面的加载. 所以,我们需要以另外一种方式进行,使用异步添加script方法.

上面就是一个精简版的JSONP了。 另外,也推荐使用jquery的getJSON和$.ajax进行请求.先看一下getJSON

这里,我们需要关注一下url里面中callback=?里的?的内涵. jquery使用自动生成数的方式, 省去了我们给回调命名的困扰。 其实,最后?会被一串字符代替,比如: json23153123. 这个就代表你的回到函数名. 不过,还是推荐使用$.ajax,因为你一不小心就有可能忘掉最后的?. 使用$.ajax发送jsonp

这样,我们就可以利用jquery很简单的发送jsonp了.

SSE

ajax和JSONP 都是 client-fetch的操作. 但是有时候, 我们更需要服务器主动给我们发信息. 比如,现在的APP应用,完全可以实现服务器发送, 然后Client再处理. 而,SSE就是帮助我们向webapp靠近. SSE 全称就是 Server-Sent Events. 中译 为 服务器推送. 他的技术并不是很难,和websocket不同,他依赖原生的HTTP,所以对于开发者来说更好理解。 比如,在nodeJS, 只要我不执行res.end(),并且一定时间持续发送信息的话,那么该连接就会持续打开(keep-alive). 其实通俗来说,就是一个长连接. 所以,以前我们通常使用ajax,iframe长轮询来代替他.但是这样有个缺点就是, 可操控性弱, 错误率高。 所以,正对于这点W3C, 觉得需要在客户端另外指定一个机制--能够保证服务器推送, 实现连接的keep-alive,操作简单... 在这样背景下SSE诞生了. 但SSE和AJAX具体的区别在什么地方呢?

  • 数据类型不同: SSE 只能接受 type/event-stream 类型. AJAX 可以接受任意类型
  • 结束机制不同: 虽然使用AJAX长轮询也可以实现这样的效果, 但是, 服务器端(nodeJS)必须在一定时间内执行res.end()才行. 而SSE, 只需要执行res.write() 即可.

简单demo

先看一个client端, 一个比较简单的demo:

SSE主要就是创建一个EventSource对象. 里面的参数就是发送的路由, 不过目前还不支持CORS,所以也被限制在同源策略下.在返回的source里面包含了,需要处理的一切信息.SSE也是通过事件驱动的,如上面demo所述. 这里,SSE通常有一下几类重要的事件.

eventName

effect

open

当连接打开时触发

message

当有数据发送时触发, 在event对象内包含了相关数据

error

当发生错误时触发

上面几个方法比较重要的还是message方法. message主要用来进行信息的接受, 回调中的event 包含了返回的相关数据.event包含的内容.

property

effect

data

服务器端传回的数据

origin

服务器端URL的域名部分,有protocol,hostname,port

lastEventId

用来指定当前数据的序号.主要用来断线重连时数据的有效性

服务器返回数据格式

上文说过,SSE 是以event-stream格式进行传输的. 但具体内容是怎样的呢?

上面就是一个简单的demo. 每一段数据我们称之为事件, 每一个事件经过空行分隔. :前面是数据类型,后面是数据. 通常的类型有:

  • 空类型: 表示注释,在处理是会默认被删除.比如: this is a comment.
  • event: 声明该事件类型,比如message.
  • data: 最重要的一个类型, 表示传输的数据。可以为string格式或者JSON格式. 比如: data: {"username": "bobby"}
  • id: 其实就是lastEventId. 用来表明该次事件在整个流中的序号
  • retry: 用来表明浏览器断开再次连接之前等待的事件(不常用)

其实上面最重要的两个字段就是data,id. 所以,我们一般获取的话就可以使用 event.dataevent.lastEventId. 上文说道, 每一段内容是通过换行实现的, 那服务器端应该怎么实现, 写入的操作呢? 同样, 这里以nodeJS 为例:

通过使用'nn'进行两次换行操作--即,产生空行即可.

使用自定义事件

服务器端不仅可以返回指定数据,还可以返回指定事件.不过默认情况下都是message事件, 但我们也可以指定事件. 比如:

这里出发的就是 myevent事件。 即, 这就是触发自定义事件的方式.在front-end 我们可以使用addEventListener 来进行监听.

服务端使用SSE

由于使用的是HTTP协议,所以对于服务端基本上没什么太大的改变. 唯一注意的就是, 发送数据使用res.write()即可,断开的时候使用res.end();

Ok~ 这里有一个demo, 大家可以打开控制台看一下. 会发现,有一个连接一直处于Content-Download状态. 该连接就是一个SSE。 兼容性 目前SSE,在市面上大受欢迎, 不过总有一个SB, 离经叛道... 居然连edge都不支持. 偶尔去翻了一下,还在underConsideration. 结果底下的评论基本都是xxxx. 有空可以去看看, 逼逼MS程序员.

websocket

websocket 不同于其他的HTTP协议,他是独立于HTTP存在的另外一种通信协议。比如,像这样的一个路径ws://websocket.example.com/,就是一个websocket 通信. 通常的实时通信并不会传输大量的内容, 所以,对于HTTP协议那种,进行连接时需要传递,cookie和request Headers来说, 这种方式的通信协议,会造成一定的时延(latency). websocket通信协议就是在这样的背景下诞生了, 他与SSE,ajax polling不同的是--双向通信.

talk is cheap, show the code

我们来看一个简单的websocket demo:

可以说上面就是一个健全的websocket 通信了. 和SSE一样,我们需要创建一个WebSocket对象, 里面的参数指定连接的路由. 而且,他也是事件驱动的.常见的事件监听有.

event

effect

open

当ws连接建立时触发

message

当有信息到来时触发

error

当连接发生错误时触发

close

当连接断开时触发

websocket 发送数据

另外,websocket 最大的特点就是可以双向通信。这里可以使用.

ws.send()方法发送数据, 不过只能发送String和二进制. 这里,我们通常call 数据叫做 Frames. 他是数据发送的最小单元.包含数据的长度和数据内容.

下面就是几种常用的发送方式:

另外还可以使用binaryType指定传输的数据格式,不过一般都用不上,就不说了. 不过需要提醒的是, send方法,一般在open和message的回调函数中调用.

websocket 接受数据

同理,和SSE差不多, 通过监听message事件,来接受server发送回来的数据. 接受其实就是通过event.data来获取. 不过, 需要和server端商量好data的类型.

那server端应该怎样处理websocket通信呢? websocket虽然是另外一种协议,不过底层还是封装了TCP通信, 所以使用nodeJS的net模块,基本就可以满足,不过里面需要设置很多的头. 这里推荐使用ws模块.

NodeJS 发送websocket数据

简单的websocket demo:

可以参考treeHouse 编写的WSdemo(http://codepen.io/matt-west/full/tHlBb)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯IMWeb前端团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AJAX
  • JSONP
    • JSONP原理
    • SSE
      • 简单demo
        • 先看一个client端, 一个比较简单的demo:
          • 服务器返回数据格式
            • 上文说过,SSE 是以event-stream格式进行传输的. 但具体内容是怎样的呢?
              • 使用自定义事件
                • 服务器端不仅可以返回指定数据,还可以返回指定事件.不过默认情况下都是message事件, 但我们也可以指定事件. 比如:
                  • 服务端使用SSE
                    • 由于使用的是HTTP协议,所以对于服务端基本上没什么太大的改变. 唯一注意的就是, 发送数据使用res.write()即可,断开的时候使用res.end();
                    • websocket
                    • websocket 不同于其他的HTTP协议,他是独立于HTTP存在的另外一种通信协议。比如,像这样的一个路径ws://websocket.example.com/,就是一个websocket 通信. 通常的实时通信并不会传输大量的内容, 所以,对于HTTP协议那种,进行连接时需要传递,cookie和request Headers来说, 这种方式的通信协议,会造成一定的时延(latency). websocket通信协议就是在这样的背景下诞生了, 他与SSE,ajax polling不同的是--双向通信.
                      • websocket 发送数据
                        • 另外,websocket 最大的特点就是可以双向通信。这里可以使用.
                          • ws.send()方法发送数据, 不过只能发送String和二进制. 这里,我们通常call 数据叫做 Frames. 他是数据发送的最小单元.包含数据的长度和数据内容.
                            • 下面就是几种常用的发送方式:
                              • websocket 接受数据
                                • NodeJS 发送websocket数据
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档