news 2026/9/21 1:56:25

web3.js WebSocket Provider(web3-providers-ws)完整指南:安装、连接、鉴权与自动重连

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
web3.js WebSocket Provider(web3-providers-ws)完整指南:安装、连接、鉴权与自动重连
  • 区块链
  • Web3

【免费下载链接】web3.js

Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.

项目地址:https://gitcode.com/gh_mirrors/we/web3.js
点击查看免费下载

web3-providers-ws是 web3.js 4.x 仓库中专用于 WebSocket 协议的 provider 子包,为通过ws:///wss://与 Ethereum 节点通信提供了基于 EIP-1193 规范、内置 JSON-RPC 请求队列与自动重连能力的连接层。本文将以该包的 README 为主线,结合 源码 与测试用例,完整讲解安装配置、WebSocketProvider构造函数参数、连接状态管理、鉴权方式、重连策略与订阅支持,帮助你在实时场景(事件订阅、推送通知)中正确选用和调优该 provider。

包定位:web3.js 的 WebSocket 连接层

web3-providers-ws是 web3.js 4.x 体系中的一个独立子包,与web3-providers-httpweb3-providers-ipc并列,专门负责 WebSocket 协议的 provider 实现(见 package.json 的描述 "Websocket provider for Web3 4.x.x")。它本身不直接依赖整个 web3.js 主包,而是基于web3-typesweb3-utilsweb3-errors等底层库构建,因此既可以作为 web3.js 内部的默认 WebSocket provider 使用,也可以脱离主包独立安装、单独作为 EIP-1193 provider 接入。

从依赖关系看(package.json),该包的核心运行时依赖包括:

  • ws^8.17.1)与isomorphic-ws^5.0.0):跨 Node.js / 浏览器环境的 WebSocket 实现,isomorphic-ws在不同环境自动选择底层适配;
  • web3-types^1.7.0):提供EthExecutionAPIWeb3APIPayload等类型定义;
  • web3-utils^4.3.1):提供SocketProvider抽象基类、ReconnectOptionsisNullish等工具;
  • web3-errors^1.2.0):提供ConnectionNotOpenErrorInvalidClientError等错误类型。

该包版本号当前为4.0.8,要求 Node.js>=14、npm>=6.12.0,并面向 ES2020 编译(见 package.json)。

安装与运行环境

使用 NPM 安装

npm install web3-providers-ws

使用 Yarn 安装

yarn add web3-providers-ws

两种安装方式等价。由于它是 web3.js monorepo 的子包,如果是在整个仓库中开发调试,也可以借助仓库根目录的 Lerna/Yarn Workspaces 机制在本地构建:在包目录执行yarn build会同时构建 CJS(lib/commonjs)、ESM(lib/esm)与类型声明(lib/types)三套产物(见 package.json)。

环境要求

  • Node.js:官方要求 LTS 版本(README 标注为 Fermium,即 Node 14.x 系列,实际engines字段为>=14);
  • 包管理器:Yarn 或 npm(>=6.12.0),monorepo 场景下也可使用 Lerna;
  • 目标协议:连接地址必须是ws://wss://开头的 URL。

快速开始:创建 WebSocketProvider

最小示例

import WebSocketProvider from 'web3-providers-ws'; const provider = new WebSocketProvider('ws://localhost:8545');

WebSocketProvider的构造函数签名如下(见 src/index.ts):

new WebSocketProvider( socketPath: string, socketOptions?: ClientOptions | ClientRequestArgs, reconnectOptions?: Partial<ReconnectOptions>, )
  • socketPath:WebSocket 地址,必须是ws://wss://前缀的合法 URL;
  • socketOptions:可选,透传给底层ws客户端的选项(如headershandshakeTimeout等);
  • reconnectOptions:可选,重连策略配置(autoReconnectdelaymaxAttempts)。

后两个参数都可省略。例如只传空对象或undefined

const provider = new WebSocketProvider('ws://localhost:8545', {}, { delay: 500, autoReconnect: true, maxAttempts: 10, });

URL 校验

构造函数会对socketPath做严格校验:只有以ws://wss://(大小写不敏感)开头的字符串才会被接受,否则抛出InvalidClientError。该校验逻辑位于 src/index.ts:

protected _validateProviderPath(providerUrl: string): boolean { return typeof providerUrl === 'string' ? /^ws(s)?:\/\//i.test(providerUrl) : false; }

单元测试 test/unit/web_socket_provider.test.ts 与测试数据 test/fixtures/test_data.ts 验证了这一点:

  • 合法示例:ws://localhost:8545ws://localhostwss://foo.comws://foo.com:8545等;
  • 非法示例:htt://localhost:8545http//localhost:8545ipc://localhost:8545、空字符串、nullundefined、数字42等,均会抛出Client URL "..." is invalid.错误。

注意:ipc://前缀不属于本包职责,IPC 连接应使用web3-providers-ipc

核心 API 与连接生命周期

WebSocketProvider继承自web3-utils中的抽象基类SocketProvider(见 web3-utils/src/socket_provider.ts),后者又继承自 EIP-1193 provider。因此该 provider 天然具备以下能力(单元测试 test/unit/web_socket_provider.test.ts 逐一验证了这些方法的存在):

API说明
request(payload)发起 JSON-RPC 请求,返回 Promise
getStatus()返回'connecting'/'connected'/'disconnected'
connect()/disconnect(code?, data?)手动建立 / 关闭连接
safeDisconnect(code?, data?, forceDisconnect?, ms?)等待请求队列清空后再断开(forceDisconnect=true时最多等待 5 次重试后强制清空)
reset()清空 pending / sent 请求队列并重置监听器
supportsSubscriptions()恒返回true,表示支持订阅
on / once / removeListener / removeAllListeners事件监听(connectdisconnectmessageerror等)
getPendingRequestQueueSize()/getSentRequestsQueueSize()查看请求队列大小
SocketConnection暴露底层 WebSocket 实例

连接状态机

getStatus()的实现直接映射底层 WebSocket 的readyState(见 src/index.ts):

  • CONNECTING→ 返回'connecting'
  • OPEN→ 返回'connected'
  • 其他(如CLOSINGCLOSED)→ 返回'disconnected'

集成测试 test/integration/web_socket_provider_integration.test.ts 完整覆盖了三种状态的流转:新建即connecting,连接建立后connected,调用disconnect()disconnected

请求与响应处理

request()是核心调用入口,其逻辑位于基类 socket_provider.ts:

  1. 若连接已断开,自动重新connect()
  2. 若请求 ID 缺失,抛出Web3WSProviderError('Request Id not defined')
  3. 若同一 ID 已存在于_sentRequestsQueue,抛出RequestAlreadySentError
  4. 为每个请求创建Web3DeferredPromise并封装为SocketRequestItem
  5. 连接尚未建立(connecting)时,请求进入_pendingRequestsQueue,待open事件触发后由_sendPendingRequests()统一补发(见 socket_provider.ts);
  6. 连接就绪时直接通过_sendToSocket发送——底层实现为this._socketConnection?.send(JSON.stringify(payload))(见 src/index.ts),并在此前检查连接状态,断开时抛出ConnectionNotOpenError

收到消息时,_parseResponses会借助ChunkResponseParser解析可能被分块(chunked)返回的响应,并按请求 ID 从_sentRequestsQueue中匹配、resolve 对应的 deferred promise;若响应是*_subscription类型的通知,则作为message事件向外抛出(见 socket_provider.ts)。集成测试 test/integration/web_socket_provider_integration.test.ts 验证了在同一连接上并发发送多个请求(eth_getBalanceeth_miningeth_hashrate)并正确按 ID 取回响应。

socketOptions:连接选项与鉴权

第二个构造参数socketOptions会被原样透传给isomorphic-ws的 WebSocket 客户端(见 src/index.ts):

protected _openSocketConnection() { this._socketConnection = new WebSocket( this._socketPath, undefined, this._socketOptions && Object.keys(this._socketOptions).length === 0 ? undefined : this._socketOptions, ); }

注意:当传入的是空对象时,会转为undefined再透传,避免干扰底层客户端默认行为。

常见选项示例

const provider = new WebSocketProvider('wss://node.example.com', { headers: { // 若节点要求 API Key 放在请求头中,例如: 'x-api-key': '<Api key>', }, handshakeTimeout: 1500, // 握手超时(毫秒) followRedirects: true, // 跟随重定向 maxRedirects: 3, // 最大重定向次数 perMessageDeflate: true, // 启用消息压缩 });

测试数据 test/fixtures/test_data.ts 中的wsProviderOptions给出了followRedirectshandshakeTimeoutmaxRedirectsperMessageDeflate等可配置项,单元测试 test/unit/web_socket_provider.test.ts 验证了携带这些选项实例化不会抛错。

通过 headers 实现鉴权

最常见的鉴权场景是把凭证放进headers。以 Basic Auth 为例,集成测试 test/integration/basic_auth.test.ts 展示了一个校验流程:服务端检查Authorization头是否包含Basic前缀,否则销毁连接。与之对应的客户端侧配置即:

const credentials = Buffer.from('username:password').toString('base64'); const provider = new WebSocketProvider('ws://localhost:3000', { headers: { Authorization: `Basic ${credentials}`, }, });

同理,对于使用 API Key 的商业节点(如 QuickNode、Infura 等),可将密钥放入headers中的自定义字段(如'x-api-key'),与源码注释中的示例一致(见 src/index.ts)。

reconnectOptions:自动重连策略

第三个构造参数控制断线重连行为。ReconnectOptions类型与默认值定义在 web3-utils/src/socket_provider.ts:

export type ReconnectOptions = { autoReconnect: boolean; delay: number; maxAttempts: number; }; const DEFAULT_RECONNECTION_OPTIONS = { autoReconnect: true, delay: 5000, maxAttempts: 5, };
参数默认值说明
autoReconnecttrue是否在异常断开后自动重连
delay5000每次重连尝试前的等待时间(毫秒)
maxAttempts5最大重连尝试次数

构造函数会通过展开运算符将用户配置合并到默认值之上(见 socket_provider.ts),因此可只传部分字段。集成测试 test/integration/reconnection.test.ts 验证了默认值确实为{ autoReconnect: true, delay: 5000, maxAttempts: 5 }

重连触发条件

重连逻辑在_onCloseEvent中判断(见 src/index.ts):

if ( this._reconnectOptions.autoReconnect && (![1000, 1001].includes(event.code) || !event.wasClean) ) { this._reconnect(); return; }

即:当自动重连开启,且关闭码不是正常的 1000(正常关闭)或 1001(服务端下线),或关闭并非干净(wasClean为 false)时,触发重连。正常关闭(如调用disconnect())则走清理队列、移除监听器、派发disconnect事件的流程。

_reconnect()的实现(见 socket_provider.ts)会:

  1. 拒绝所有_sentRequestsQueue中的请求并抛出PendingRequestsOnReconnectingError
  2. delay毫秒后重新connect()
  3. 若重连次数达到maxAttempts上限,则清空队列并抛出MaxAttemptsReachedOnReconnectingError

重连配置示例

const provider = new WebSocketProvider( 'ws://localhost:8545', {}, { delay: 500, // 每 500ms 尝试一次 autoReconnect: true, maxAttempts: 10, // 最多尝试 10 次 }, );

需要快速失败(例如测试或容错场景)时可显式关闭重连,如集成测试中常用的{ delay: 1, autoReconnect: false, maxAttempts: 1 }(见 test/integration/web_socket_provider_integration.test.ts);与此相对,test/integration/reconnection.test.ts 使用{ delay: 500, autoReconnect: true, maxAttempts: 100 }验证长时间重连场景。

事件订阅:实时推送的基础

由于 WebSocket 是双向通道,该 provider 支持 JSON-RPC 订阅(eth_subscribe/eth_unsubscribe)。supportsSubscriptions()恒返回true(见 socket_provider.ts),单元测试也对此做了断言(见 test/unit/web_socket_provider.test.ts)。

订阅推送的消息会以*_subscription结尾的方法名被识别为通知,通过message事件向外派发。监听方式:

provider.on('message', (result) => { console.log('收到订阅推送:', result); });

其他可用事件包括:

  • connect:连接建立成功(对应open事件,见 socket_provider.ts);
  • disconnect:连接关闭,回调参数为ProviderRpcError(含codereason);
  • error:底层 WebSocket 出错,或请求失败时派发(见 socket_provider.ts)。

集成测试 test/integration/web_socket_provider_integration.test.ts 完整覆盖了messageerrorconnectdisconnect四个事件的订阅,并验证了连接未建立时调用request()会抛出Connection not open错误。

与 web3.js 主包集成

web3-providers-ws不仅可独立使用,也是 web3.js 4.x 主包中eth模块默认使用的 WebSocket provider。你可以直接在Web3实例上指定:

import Web3 from 'web3'; import WebSocketProvider from 'web3-providers-ws'; const provider = new WebSocketProvider('wss://node.example.com', { headers: { 'x-api-key': '<Api key>' }, }); const web3 = new Web3(provider); // 之后即可使用 web3.eth.getBlockNumber()、web3.eth.subscribe(...) 等 API

这样既能复用 provider 的自动重连与请求队列,又能借助主包获得合约、交易、订阅等完整 API。

包内常用脚本

开发本包时可使用 package.json 中定义的脚本:

Script说明
clean使用rimraf删除dist/lib/
build使用tsc构建本包及其依赖包(CJS/ESM/类型三套产物)
lint使用eslint检查代码
lint:fix使用eslint检查并自动修复
format使用prettier格式化代码
test运行单元测试(jest,配置见test/unit/jest.config.js
test:integration运行test/integration下的集成测试(需连接真实节点,测试中通过getSystemTestProviderUrl()获取)
test:unit仅运行单元测试

单元测试在test/unit下(mock 了isomorphic-ws),集成测试在test/integration下(依赖真实 WebSocket 节点,并通过describeIf(isWs)条件执行),源码入口为 src/index.ts,默认导出WebSocketProvider

小结

web3-providers-ws为 web3.js 4.x 提供了开箱即用的 WebSocket 连接能力:通过new WebSocketProvider(url, socketOptions?, reconnectOptions?)三参数构造即可完成连接、鉴权与重连策略配置;其基于 EIP-1193 的SocketProvider基类封装了请求队列、分块响应解析、自动重连与订阅分发,适合事件监听、实时推送等场景。在使用时,请重点根据节点要求配置headers(鉴权)、按网络稳定性调优reconnectOptions(重连间隔与次数上限),并善用connect/disconnect/message/error事件掌握连接生命周期。

  • 区块链
  • Web3

【免费下载链接】web3.js

Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.

项目地址:https://gitcode.com/gh_mirrors/we/web3.js
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 1:51:42

EC2302触摸芯片调试实战:电容传感校准与PCB物理设计要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 1:49:15

Voyager Timeline:将 Gemini 长对话变成可即时跳转的可视化时间轴

AI 应用前端 【免费下载链接】voyager Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件&#xff1b;其中的提示词管理器可用…

作者头像 李华
网站建设 2026/9/21 1:48:39

SimCLR自监督预训练实战:TensorFlow 2.13完整实现

简介&#xff1a;本资源是一份基于TensorFlow2实现SimCLR自监督学习算法的完整工程实践包&#xff0c;面向深度学习初学者与图像领域开发者&#xff0c;解决无标签数据下特征预训练与下游分类任务迁移的实际问题。资源共3383个文件&#xff0c;主体为3360张tif格式图像样本&…

作者头像 李华
网站建设 2026/9/21 1:48:09

在 Snowpack 中集成 PostCSS:@snowpack/plugin-postcss 完整使用指南

在 Snowpack 中集成 PostCSS&#xff1a;snowpack/plugin-postcss 完整使用指南 【免费下载链接】snowpack ESM-powered frontend build tool. Instant, lightweight, unbundled development. ✌️ 项目地址: https://gitcode.com/gh_mirrors/sn/snowpack snowpack/plug…

作者头像 李华