[深入15] WebSocket

导航 [[深入01] 执行上下文](https://juejin.im/post/684490...
[[深入02] 原型链](https://juejin.im/post/684490...
[[深入03] 继承](https://juejin.im/post/684490...
[[深入04] 事件循环](https://juejin.im/post/684490...
[[深入05] 柯里化 偏函数 函数记忆](https://juejin.im/post/684490...
[[深入06] 隐式转换 和 运算符](https://juejin.im/post/684490...
[[深入07] 浏览器缓存机制(http缓存机制)](https://juejin.im/post/684490...
[[深入08] 前端安全](https://juejin.im/post/684490...
[[深入09] 深浅拷贝](https://juejin.im/post/684490...
[[深入10] Debounce Throttle](https://juejin.im/post/684490...
[[深入11] 前端路由](https://juejin.im/post/684490...
[[深入12] 前端模块化](https://juejin.im/post/684490...
[[深入13] 观察者模式 发布订阅模式 双向数据绑定](https://juejin.im/post/684490...
[[深入14] canvas](https://juejin.im/post/684490...
[[深入15] webSocket](https://juejin.im/post/684490...
[[深入16] webpack](https://juejin.im/post/684490...
[[深入17] http 和 https](https://juejin.im/post/684490...
[[深入18] CSS-interview](https://juejin.im/post/684490...
[[深入19] 手写Promise](https://juejin.im/post/684490...
[[深入20] 手写函数](https://juejin.im/post/684490...
[[react] Hooks](https://juejin.im/post/684490...
[[部署01] Nginx](https://juejin.im/post/684490...
[[部署02] Docker 部署vue项目](https://juejin.im/post/684490...
[[部署03] gitlab-CI](https://juejin.im/post/684490...
【[深入15] WebSocket】[[源码-webpack01-前置知识] AST抽象语法树](https://juejin.im/post/684490...
[[源码-webpack02-前置知识] Tapable](https://juejin.im/post/684490...
[[源码-webpack03] 手写webpack - compiler简单编译流程](https://juejin.im/post/684490...
[[源码] Redux React-Redux01](https://juejin.im/post/684490...
[[源码] axios ](https://juejin.im/post/684490...
[[源码] vuex ](https://juejin.im/post/684490...
[[源码-vue01] data响应式 和 初始化渲染 ](https://juejin.im/post/684490...
[[源码-vue02] computed 响应式 - 初始化,访问,更新过程 ](https://juejin.im/post/684490...
前置知识 一些单词

specify:指定 stable:稳定的 amount:合计 optional:可选的 optional object:可选对象 ordinary:普通的 omitted:省略的 broadcast:广播 outdated:过时的

NRM - nrm
  • nrm 的作用是 ( 切换npm源 ) (npm的注册表管理器,可以切换npm的镜像地址)
  • npm, cnpm, taobao, nj(nodejitsu)等
  • command:命令
  • 全局安装后,报错处理
    • nrm : 无法加载文件 D:\Program Files\nodejs\nrm.ps1,因为在此系统上禁止运行脚本。
    • 解决办法:
      • (1) 用管理员身份打开cmd,输入以下命令
      • (2) set-ExecutionPolicy RemoteSigned命令将计算机上的执行策略更改为 RemoteSigned,输入Y确定
    • ExecutionPolicy:执行策略
    • 执行策略可以帮助你执行不信任的脚本
    (1) install npm install -g nrm(2) useage nrm [options] [command] options -h,--help //----------------------------------- help -V,--version //-------------------------------- version numbercommonds nrm ls //------------------------------------------- 列出所有源 nrm use //------------------------------- 使用具体哪个源 nrm add [home] //------------------ 添加源,(1) registry是源的名字,可以随便取 (2) url源地址 nrm del //------------------------------- 删除源 nrm test [registry] // ----------------------------- 测速,返回响应的时间

NVM - nvm
  • nvm 用于切换 node 和 npm 版本
  • windows系统上可以用 nvm-windows
  • [教程:]()
  • 注意事项 !!!!!!!
    • 如果之前安装过node即系统中存在node,需要将node卸载干净,步骤如下

useagenvm use [arch] //------------------ 使用哪个版本的node,(arch表示32位或64位,非必须) mvm list [available] // --------------------- 展示可用的node版本列表,(available表示有效,非必须) nvm install [arch] // ------------- 安装指定的node版本,version表示具体的版本号 nvm uninstall

---- 查看全局安装的包:----------------- npm ls -g --depth=0 查看全局安装的包:----------------- npm list -g --depth=0 // ls 和 list 都可以 卸载本地全局安装包:--------------- npm uninstall -g xxxx 查看需要更新的全局包:------------- npm outdated -g --depth=0 // outdated是过时的意思npm info xxxx // ------------------------------ 远程包的信息 npm info xxxx version // ---------------------- 远程最新的版本号 npm info xxxx versions // --------------------- 远程所有版本号

window.postMessage 跨域通信
  • window.postMessage 可以实现跨域信息交互,两个web浏览器标签页之间的通信IFrame 通信等
  • otherWindow.postMessage(message, targetOrigin, [transfer]);
  • 注意:在targetWindow.open()后,要等到目标页面加载完成才能进行 postMessage 跨域通信,但是在跨域的情况下,无法对目标窗口进行onload监听,所以可以用 setTimeout延时,对于IFrame同理
(一) otherWindow.postMessage(message, targetOrigin, [transfer]) 跨域通信(1) otherWindow - otherWindow指的是其他窗口的一个引用 1. iframe 的 contentWindow 属性 2. window.open() 返回的一个窗口对象 3. 命名过或数值索引的 window.frames 4. 两个窗口之间 - a -> b,otherWindow是b窗口 - b -> a,otherWindow是a窗口,即 ( top ) 或者 ( parent )(2) message - message指发送给其他窗口的数据 - message会被序列化,所以无需自己序列化(3) targetOrigin!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - targetOrigin:设置目标窗口的源(协议域名端口组成的字符串),指定哪些窗口能 ( 接收 ) 到消息事件 - 在 ( 发消息 ) 的时候,如果( 目标窗口 ) 的 ( 协议,域名,端口) 任意一项不满足 targetOrigin 提供的值,消息就不会发送 - 三者要全部匹配才会发送 - targetOrigin的值可以是 (*) 号,表示所有窗口都能接收到消息(4) transfer - transfer 是一串和message同时传递的 Transferable 对象 - 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权发消息:--------------- otherWindow.postMessage(message, targetOrigin, [transfer]) 收消息:--------------- window.addEventListener('message', (data) => {console.log(data.data, data.origin)}, false) 注意:----------------- 通过 ( targetOrigin - 验证接收方 ) 和 ( data.origin - 验证发送方 ) 来精确通信- data.origin 和 data.source 和 data.data - 在接收端的监听函数中,注意 origin 和 source - origin: ------------- 发送方的协议,域名,端口组成的字符串 - source:------------- 发送方窗口对象的引用 - data:--------------- 接收到的数据 window.addEventListener("message", receiveMessage, false); // 接收消息的tab标签页面监听message事件 function receiveMessage(event) { // For Chrome, the origin property is in the event.originalEvent // object. // 这里不准确,chrome没有这个属性 // var origin = event.origin || event.originalEvent.origin; var origin = event.origin if (origin !== "http://example.org:8080") return; // ... }(二) 注意事项: - 使用postMessage将数据发送到其他窗口时,始终要指定精确的目标origin,而不是使用 * - 使用 origin 和 source 验证 ( 发件人 ) 的身份(三) 实例:-------------- a页面 Document - 锐客网 点击,打开b页面 点击,发送消息,a->b--------------- b页面 Document - 锐客网 b页面


websocket概述
  • websocket是应用层协议的一种,建立在http协议之上,是一种双向通信的协议
  • HTTP在1.1版本中也能建立长连接 Connection:Keep-alive
    • 但是 ( HTTP ) 建立的长连接本质上还是 request response 这样的形式,即 ( 一个request对应一个response )
    • 而 ( websocket ) 是 ( 全双工通信 )
  • TCP是传输层协议
  • HTTP 和 websocket 是应用层的协议
  • IP是网络层协议

WebSocket 客户端api new WebSocket(url)
  • const ws = new WebSocket('ws://localhost:8080')
  • WebSocket 作为构造函数,用于新建 websocket 实例
  • ws:表示websocket协议
  • wss:表示websocket加密协议
webSocket.readyState
  • readyState 属性返回实例对象的当前状态,一共4种
    CONNECTING:0 --------------- 表示正在连接 OPEN: 1 --------------------- 表示连接成功,可以通信了 CLOSING:2 ------------------ 表示连接正在关闭 CLOSED:3 ------------------- 表示连接已经关闭,或者连接打开失败

webSocket.onopen
  • 指定连接成功后的回调函数
  • 指定一个回调函数:ws.onopen = function(){}
  • 指定多个回调函数:ws.addEventListener('open', function(){})
webSocket.onclose
  • 指定连接关闭后的回调函数
webSocket.onmessage
  • 指定收到服务器数据后的回调函数
  • 注意:服务器返回的数据有两种可能 ( 文本 ) 或 ( 二进制数据 - blob对象或Arraybuffer对象 )
  • 判断数据数据类型: binaryType
    • ws.binaryType = 'blob'
    • ws.binaryType = 'arraybuffer'
    • binary:二进制的
    ws.onmessage = function(event) { var data = https://www.it610.com/article/event.data; // 处理数据 }; ws.addEventListener("message", function(event) { var data = https://www.it610.com/article/event.data; // 处理数据 }); ----------ws.onmessage = function(event){ if(typeof event.data === String) { console.log("Received data string"); }if(event.data instanceof ArrayBuffer){ var buffer = event.data; console.log("Received arraybuffer"); } }

webSocket.send()
  • wx.send() 用于向服务器发送数据
webSocket.bufferedAmount
  • wx.bufferedAmount 表示还有多少字节的二进制数据没有发送出去,可以用来判断是否发送结束
  • wx.bufferedAmount === 0 表示发送结束
  • amount:合计的意思
webSocket.onerror
  • wx.onerror 指定报错时的回调函数
使用 websocket 和 nodejs-websocket 简单聊天室
客户端: Document - 锐客网

服务端: const ws = require('nodejs-websocket')const server = ws.createServer(function(conn) { console.log("New connection") conn.on("text", function (str) { // ------------------------ 客户端发来的数据是text类型时触发 console.log("Received "+str) // conn.sendText(str) const data = https://www.it610.com/article/JSON.parse(str)switch(data.type) { case'name': conn.nickname = data.value; broadcast(data.value + '加入了房间'); break; case 'chat': console.log(data.value, 'data.value'); broadcast(data.value); break; default: break; } }) function broadcast(str) { // --------------------------------------- broadcast:广播 server.connections.forEach((conn) => { conn.sendText(str) }) } conn.on("close", function (code, reason) { // --------------------- 关闭连接时触发 console.log("Connection closed") broadcast(conn.nickname + '离开了房间') }) // conn.send('服务端 => 发给客服端的消息') conn.on('error', (err) => { // -------------------------------------- 处理错误 console.log(err) }) }) server.listen(5555, () => console.log('server runing')) // ------------- 监听端口


资料 https://juejin.im/post/684490...
阮一峰 http://www.ruanyifeng.com/blo...
nvm 和 nrm https://juejin.im/post/684490...
nrm官网:https://github.com/Pana/nrm
nrn安装后输入命令报错:https://blog.csdn.net/ougexin...
nodejs-websocket:https://github.com/sitegui/no...
otherWindow.postMessage:https://juejin.im/entry/68449...

    推荐阅读