当前位置: 首页 > news >正文

前端封装WebSocket工具n

  1. Web API 提供的 WebSocket 类,封装一个 Socket 类
// socket.js
import modal from '@/plugins/modal'
const baseURL = import.meta.env.VITE_APP_BASE_WS;
const EventTypes = ['open', 'close', 'message', 'error', 'reconnect'];
const DEFAULT_CHECK_TIME = 55 * 1000; // 心跳检测的默认时间
const DEFAULT_CHECK_COUNT = 3; // 心跳检测默认失败重连次数
const DEFAULT_CHECK_DATA = { Type: 1, Parameters: ['alive'] }; // 心跳检测的默认参数 - 跟后端协商的
const CLOSE_ABNORMAL = 1006; // WebSocket非正常关闭code码class EventMap {deps = new Map();depend(eventType, callback) {this.deps.set(eventType, callback);}notify(eventType, event) {if (this.deps.has(eventType)) {this.deps.get(eventType)(event);}}
}class Socket extends WebSocket {heartCheckData = DEFAULT_CHECK_DATA;heartCheckTimeout = DEFAULT_CHECK_TIME;heartCheckInterval = null;heartCheckCount = DEFAULT_CHECK_COUNTconstructor(options, dep, reconnectCount = 0) {let _baseURL = baseURLconst { url, protocols, query = {}, greet = null, customBase = null } = options;const _queryParams = Object.keys(query).reduce((str, key) => {if (typeof query[key] !== 'object' && typeof query[key] !== 'function') {return str += str.length > 0 ? `&${key}=${query[key]}` : `${key}=${query[key]}`;} else {return str;}}, '');if (customBase) {_baseURL = customBase}super(`${_baseURL}${url}?${_queryParams}`, protocols);this._currentOptions = options;this._dep = dep;this._reconnectCount = reconnectCount;greet && Object.assign(this, {heartCheckData: greet})this.initSocket();}// 初始化WebSocketinitSocket() {// 监听webSocket的事件this.onopen = function (e) {this._dep.notify('open', e);this.heartCheckStart();}this.onclose = function (e) {this._dep.notify('close', e);// 如果WebSocket是非正常关闭 则进行重连if (e.code === CLOSE_ABNORMAL) {if (this._reconnectCount < this.heartCheckCount) {this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return modal.msgError('WebSocket重连失败, 请联系技术客服!');}}}this.onerror = function (e) {this._dep.notify('error', e);}this.onmessage = function (e) {// 如果后端返回的是二进制数据if (e.data instanceof Blob) {const reader = new FileReader()reader.readAsArrayBuffer(e.data)reader.onload = (ev) => {if (ev.target.readyState === FileReader.DONE) {this._dep.notify('message', ev.target?.result);}}} else {// 处理普通数据try {const _parseData = JSON.parse(e.data);this._dep.notify('message', _parseData);} catch (error) {console.log(error)}}}}// 订阅事件subscribe(eventType, callback) {if (typeof callback !== 'function') throw new Error('The second param is must be a function');if (!EventTypes.includes(eventType)) throw new Error('The first param is not supported');this._dep.depend(eventType, callback);}// 发送消息sendMessage(data, options = {}) {const { transformJSON = true } = options;let result = data;if (transformJSON) {result = JSON.stringify(data);}this.send(result);}// 关闭WebSocketcloseSocket(code, reason) {this.close(code, reason);}// 开始心跳检测heartCheckStart() {this.heartCheckInterval = setInterval(() => {if (this.readyState === this.OPEN) {let transformJSON = typeof this.heartCheckData === 'object'this.sendMessage(this.heartCheckData, { transformJSON });} else {this.clearHeartCheck();}}, this.heartCheckTimeout)}// 清除心跳检测clearHeartCheck() {clearInterval(this.heartCheckInterval);}// 重置心跳检测resetHeartCheck() {clearInterval(this.heartCheckInterval);this.heartCheckStart();}
}
// 默认的配置项
const defaultOptions = {url: '',protocols: '',query: {},
}export const useSocket = (options = defaultOptions) => {if (!window.WebSocket) return modal.msgWarning('您的浏览器不支持WebSocket, 请更换浏览器!');const dep = new EventMap();const reconnectCount = 0;return new Socket(options, dep, reconnectCount);
}
  1. 使用这个封装好的 useSocket 函数,以在 Vue3中使用为例
// xx.jsx or xx.vue
import { useSocket } from './socket.js'
const socket = ref(null) // WebSocket实例
const initWebSocket = () => {const options = {url: '/<your url>',query: {// something params},}socket.value = useSocket(options)socket.value.subscribe('open', () => {console.log('WebSocket连接成功!')const greet = 'hello'// 发送打招呼消息socket.value.sendMessage(greet)})socket.value.subscribe('close', reason => {console.log('WebSocket连接关闭!', reason)})socket.value.subscribe('message', result => {console.log('WebSocket接收到消息:', result)})socket.value.subscribe('error', err => {console.log('WebSocket捕获错误:', err)})socket.value.subscribe('reconnect', _socket => {console.log('WebSocket断开重连:', _socket)socket.value = _socket})
}
initWebSocket()
  1. debug 我们的心跳检测是否有效
// 测试心跳检测重连 手动模拟断开的情况
if (this._reconnectCount > 0) return;
const tempTimer = setInterval(() => {this.close();if (this._reconnectCount < 3) {console.log('重连');this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return clearInterval(tempTimer);}
}, 3 * 1000)

相关文章:

前端封装WebSocket工具n

Web API 提供的 WebSocket 类&#xff0c;封装一个 Socket 类 // socket.js import modal from /plugins/modal const baseURL import.meta.env.VITE_APP_BASE_WS; const EventTypes [open, close, message, error, reconnect]; const DEFAULT_CHECK_TIME 55 * 1000; // 心…...

Docker进入MySQL之后如何用sql文件初始化数据

关闭Docker-compose.yml里面所有容器 docker compose -f docker_compose.yml down后台形式开启Docker-compose.yml所有容器 docker compose -f docker_compose.yml up -d罗列出所有启动过的&#xff08;包括退出过的&#xff09;容器 docker ps -a进入指定容器ID内部 docke…...

Docker搜索镜像报错

科学上网最方便。。。。 尝试一&#xff1a; 报错处理 Error response from daemon: Get https://index.docker.io/v1/search?qmysql&n25: dial tcp 31.13.84.2:443: i/o timeout 国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;此时可以配置镜像加速器。Docke…...

【Unity笔记】基于距离驱动的参数映射器 InverseDistanceMapper 设计与实现

需求&#xff1a; 当用户距离目标位置越近&#xff0c;参数值越大。 可用于控制场景亮度、动画进度、交互强度等多种效果。 一、需求背景&#xff1a;如何让“距离”成为设计的一部分&#xff1f; 在虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;乃…...

【Spring AI】Java结合ollama实现大模型调用

在较新的Java版本中&#xff0c;编译器已经支持了接入各种AI模型工具进行开发&#xff0c;这篇文章我会介绍如何利用Spring AI进行大模型的调用的基础方法。 环境准备 由于这篇文章是结合ollama进行演示&#xff0c;所以在开始前需要先安装ollama服务&#xff0c;这个的具体步…...

docker制作python大模型镜像(miniconda环境),工程改造记录

**环境说明&#xff1a;**从系统镜像开始打造python大模型镜像&#xff0c;之前是人工手动装的方式&#xff0c;并且模型和依赖在公网中&#xff0c;对于离线交付环境不太友好&#xff0c;所以打造的离线化交付版本 Dockerfile: FROM centos:7.9 ENV PYTHONIOENCODINGutf-8 E…...

在油气地震资料积分法偏移成像中,起伏地表处理

在油气地震资料积分法偏移成像中&#xff0c;起伏地表情况会带来波场传播路径畸变、静校正问题以及成像精度下降等挑战。以下是处理起伏地表的常用方法和技术要点&#xff1a; 1. 静校正预处理 高程静校正&#xff1a;将地表各接收点校正到统一基准面&#xff08;浮动基准面或…...

经典算法 独立任务最优调度问题

独立任务最优调度问题 题目描述 用2 台处理机A 和B 处理n 个作业。设第i 个作业交给机器A 处理时需要时间ai &#xff0c;若由机器B 来处理&#xff0c;则需要时间bi 。由于各作业的特点和机器的性能关系&#xff0c;很可能对于某些i&#xff0c;有ai >bi&#xff0c;而对…...

在TensorFlow中,`Dense`和`Activation`是深度学习模型构建里常用的层

在TensorFlow中&#xff0c;Dense和Activation是深度学习模型构建里常用的层&#xff0c;下面就详细解释它们的使用语法和含义。 1. Dense层 含义 Dense层也就是全连接层&#xff0c;这是神经网络里最基础的层。在全连接层中&#xff0c;每一个输入神经元都和输出神经元相连…...

基于 Rancher 部署 Kubernetes 集群的工程实践指南

一、现状分析 在当今的云计算和容器化领域&#xff0c;Kubernetes&#xff08;K8S&#xff09;已经成为了容器编排和管理的事实标准。根据 Gartner 的数据&#xff0c;超过 70% 的企业在生产环境中使用 K8S 来管理容器化应用。然而&#xff0c;K8S 的安装和管理对于许多企业来…...

Seaborn

1. Seaborn概述&#xff1a;Seaborn是基于Matplotlib的Python数据可视化库&#xff0c;专注绘制统计图形。它简化可视化流程&#xff0c;提供高级接口与美观默认主题&#xff0c;能以少量代码实现复杂图形绘制。 2. 安装与导入&#xff1a;安装Seaborn可使用 pip install seabo…...

0基础FWT详解2(巩固)

FWT巩固1 FWT巩固1卡常技巧巩固习题luogu6097CF662Cluogu4221FWT巩固1 在 上篇文章 中,我们学习了 F W T FWT FWT,本文将带读者一起做几道题,巩固对 F W T FWT FWT 的使用 卡常技巧 一个常数大的 F W T FWT FWT 是非常不利于做题的,所以我们需要卡常。 作者简单总结…...

阿里云 ECS 服务器进阶指南:存储扩展、成本优化与架构设计

一、弹性存储架构&#xff1a;块存储深度解析与挂载实践 &#xff08;一&#xff09;块存储类型与技术特性 阿里云块存储作为 ECS 核心存储方案&#xff0c;提供三种主流类型&#xff1a; ESSD 云盘 性能等级&#xff1a;PL0/PL1/PL2/PL3&#xff0c;最高支持 100 万 IOPS …...

运维打铁: 存储方案全解析

文章目录 一、引言二、思维导图三、常见存储方案介绍3.1 直接附加存储&#xff08;DAS&#xff0c;Direct Attached Storage&#xff09;1. 原理2. 优缺点3. 适用场景 3.2 网络附加存储&#xff08;NAS&#xff0c;Network Attached Storage&#xff09;1. 原理2. 优缺点3. 适用…...

Semtech公司简介以及主流产品

Semtech 公司是一家美国的半导体公司&#xff0c;总部位于加利福尼亚州卡马里洛。以下是其简介和主流产品介绍&#xff1a; 公司简介 成立时间与地点&#xff1a;1960 年成立于加利福尼亚州纽伯里帕克。发展历程&#xff1a;最初为军事和航空航天公司提供零部件&#xff0c;1…...

flutter 专题 五十六 Google 2020开发者大会Flutter专题

由于疫情的原因&#xff0c;今年的Google 开发者大会 (Google Developer Summit) 在线上举行&#xff0c;本次大会以“代码不止”为主题&#xff0c;全面介绍了产品更新以及一系列面向本地开发者的技术支持内容。我比较关注的是移动开发&#xff0c;在本次大会上&#xff0c;关…...

93. 后台线程与主线程更新UI Maui例子 C#例子

在.NET MAUI开发中&#xff0c;多线程是常见的需求&#xff0c;但UI更新必须在主线程上执行。今天&#xff0c;我们来探讨一个简单而优雅的解决方案&#xff1a;MainThread.InvokeOnMainThreadAsync。 一、背景 在跨平台应用开发中&#xff0c;后台线程常用于执行耗时操作&am…...

5.运输层

5. 运输层 1. 概述 第2~4章依次介绍了计算机网络体系结构中的物理层、数据链路层和网络层&#xff0c;它们共同解决了将主机通过异构网络互联起来所面临的问题&#xff0c;实现了主机到主机的通信然而在计算机网络中实际进行通信的真正实体&#xff0c;是位于通信两端主机中的…...

ActiveMQ 可靠性保障:消息确认与重发机制(二)

ActiveMQ 重发机制 重发机制的原理与触发条件 ActiveMQ 的重发机制是确保消息可靠传输的重要手段。当消息发送到 ActiveMQ 服务器后&#xff0c;如果消费者由于某些原因未能成功处理消息&#xff0c;ActiveMQ 会依据配置的重发策略&#xff0c;将消息重新放入队列或主题中&am…...

Vue+tdesign t-input-number 设置长度和显示X号

一、需求 Vuetdesign t-input-number 想要设置input的maxlen和显示X号 二、实现 t-input&#xff0c;可以直接使用maxlength和clearable属性 <t-input v-model"value" clearable maxlength10 placeholder"请输入" clear"onClear" blur&q…...

机器学习|通过线性回归了解算法流程

1.线性回归引入 2.决策函数 3. 损失函数 4.目标函数 5.目标函数优化问题 6.过拟合 7.正则化...

两向量平行公式、向量与平面平行公式、两平面平行公式;两向量垂直公式、向量与平面垂直公式、两平面垂直公式

目录 一、两向量平行公式​ 二、向量与平面平行公式​ 三、两平面平行公式​ 四、两向量垂直公式​ 五、向量与平面垂直公式​ 六、两平面垂直公式​ 观察与总结 一、两向量平行公式 二、向量与平面平行公式 三、两平面平行公式 四、两向量垂直公式 五、向量与平…...

vscode 个性化

vscode 个性化 设置 吸顶效果 使用前使用后 设置方法 VS Code 的粘性滚动预览 - 类似于 Excel 的冻结首行 插件 代码片段分享 - CodeSnap 使用方式 CtrlShiftP输入CodeSnap 唤起插件选择代码 行内报错提示 - Error Lens 使用前使用后 VSCode Error Lens插件介绍&…...

OpenHarmony-简单的HDF驱动

学习于&#xff1a;https://docs.openharmony.cn/pages/v5.0/zh-cn/device-dev/driver/driver-hdf-manage.md 首先&#xff0c;OpenHarmony系统里的HDF&#xff08;Hardware Driver Foundation&#xff09;驱动框架&#xff0c;已经规范设备驱动的模型、设备节点的配置与统一的…...

Copilot重磅更新:引用文件夹创建Word文档

大家好&#xff0c;AI技术笔记为您带来一则好消息&#xff1a; 根据广大用户的反馈&#xff0c;Microsoft 365 Copilot在Word中的引用能力全面升级啦&#xff01; 不管是撰写、审阅还是定稿文档&#xff0c;现在你可以更快、更高效地引用更多资料&#xff01; ✨三大重磅改进…...

SQL Server数据库提权的几种方法——提权教程

SQL Server数据库提权的几种方法——提权教程 一、简介 在利用系统溢出漏洞没有效果的情况下,可以采用数据库进行提权。 数据库提权的前提条件: 1、服务器开启数据库服务 2、获取到最高权限用户密码 (除Access数据库外,其他数据库基本都存在数据库提权的可能) 二、使用x…...

解决在Mac上无法使用“ll”命令

在 macOS 上&#xff0c;ll 命令是一个常见的别名&#xff0c;它通常是指向 ls -l 的。但是&#xff0c;如果你看到 zsh: command not found: ll&#xff0c;这意味着你当前的 zsh 配置中没有设置 ll 作为别名。 解决方法&#xff1a; 1. 使用 ls -l 命令 如果只是想查看目录…...

Dockerfile最佳实践:构建高效、安全的容器镜像

一、前言 Dockerfile是一个文本文档,它包含用户可以在命令行上调用的所有指令,每一条指令构建一层镜像。在日常开发中我们常常需要自己编写Dockerfile来构建镜像,而构建一个精巧、实用且高品质的镜像对运行环境来说尤为重要。下面我们来排一排如何构建这样的镜像。 二、目…...

mac电脑pytest生成测试报告

时隔了好久再写代码&#xff0c;感觉我之前的积累都白费了&#xff0c;全部忘记了&#xff0c;看来每一步都有记录对于我来说才是最好的。 最近又要重新搞接口自动化&#xff0c;然而是在mac电脑&#xff0c;对于我长期使用windows的人来说真的是个考验&#xff0c;对此次过程…...

鸿蒙 应用开发 项目资源结构及资源访问

三层工程结构 模块分类 使用...

C#学习第20天:垃圾回收

什么是垃圾回收&#xff1f; 定义&#xff1a;垃圾回收是一种自动内存管理机制&#xff0c;负责回收不再使用的对象所占用的内存。目的&#xff1a;通过自动化内存回收&#xff0c;减少内存泄漏的风险&#xff0c;并简化开发者的工作。 垃圾回收的核心概念 1. 垃圾回收器的工…...

C#学习笔记 项目引用添加异常

这个问题出现多次了 我觉得有必要记录一下 场景 同一个解决方案下添加了多个项目 我想在单元测试项目中引用一下项目1&#xff0c;按照步骤&#xff1a;添加引用- 项目- 浏览- 在指定目录下找到项目的工程文件XXXSystem.csproj- 确定 然后就触发了异常 解决方案 首先 清理解决…...

使用模块中的`XPath`语法提取非结构化数据

想要在代码中使用Xpath进行处理&#xff0c;就需要模块lxml 模块安装 pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simplelxml的使用 使用lxml转化为Element对象 from lxml import etreetext <div> <ul> <li class"item-1"><a …...

复杂度和顺序表(双指针方法)

目录 目录 目录 前言&#xff1a; 一、时间复杂度和空间复杂度 1.1概念 1.2规则 二、顺序表 2.1静态顺序表 2.2动态顺序表 三、双指针法 四、总结 前言&#xff1a; 时间复杂度和空间复杂度是用于判断算法好坏的指标&#xff0c;程序性能的核心指标。时间复杂度主要衡…...

day006-实战练习题-参考答案

老男孩教育-99期-实战练习题 1. 你作为"老男孩教育99期云计算"新晋运维工程师&#xff0c;在入职首日遭遇紧急事件&#xff1a; "生产环境3台Web服务器突发性能告警&#xff0c;技术总监要求你立即完成&#xff1a; 快速建立故障诊断工作区收集关键系统指标分…...

批量删除OpenStack实例

在Linux终端实现批量删除OpenStack实例&#xff0c;支持并发删除、安全确认、重试机制、优先清理运行中实例 #!/bin/bash # # 增强版 OpenStack 删除实例脚本 # 功能&#xff1a;支持并发删除、安全确认、重试机制、优先清理运行中实例 # 更新&#xff1a;2025年4月30日 # ##…...

楼宇智能化一、二章【期末复习】

一章、楼宇概述 智能建筑的定义:以建筑物为平台,基于对各类智能化信息的综合应用,集架构、系统、应用、管理及优化组合为一体,具有感知、传输、记忆、推理、判断和决策的综合智慧能力,形成以人、建筑、环境互为协调的整合体,为人们提供安全、高效、便利及可持续发展功能…...

三生原理与西方哲学的具体对比?

AI辅助创作&#xff1a; 一、本体论差异 ‌生成论与构成论的分野‌ 三生原理以《周易》“太极生两仪&#xff0c;两仪生四象&#xff0c;四象生八卦”、《道德经》“道生一&#xff0c;一生二&#xff0c;二生三&#xff0c;三生万物”为基础&#xff0c;构建动态层级生成的宇…...

呼叫中心座席管理系统:智能升级,高效服务

在数字化转型加速的今天&#xff0c;客户服务体验已成为企业竞争力的核心要素。传统 呼叫中心系统 依赖硬件设备、人工操作的模式已无法满足高效、智能、灵活的现代企业需求。畅信达呼叫中心 座席管理系统 V5.0应运而生&#xff0c;以WEBRTC软电话接入、智能座席辅助、知识库管…...

PCB设计实战技巧宝典:从库管理到布线优化的全流程解析

知识点1【PCB设计流程】 器件 符号 封装 &#xff08;3D模型 实物图 &#xff09; 流程介绍 1、如果没有需要的的库&#xff0c;先画库&#xff1a;器件&#xff0c;符号&#xff0c;封装 2、新建工程&#xff0c;放置器件在原理图 3、原理图转PCB 4、导出ROM和Gerber…...

微信小程序 XSS 防护知识整理

场景1&#xff1a;用户输入表单&#xff08;如评论框&#xff09; 错误做法&#xff1a;直接渲染未过滤的用户输入 // WXML <view>{{ userInput }}</view>// JS&#xff08;用户输入了恶意内容&#xff09; Page({data: { userInput: <script>alert("…...

平衡截断(Balanced Truncation)—— MTALAB 和 Python 实现

平衡截断balreal 算法原理平衡截断过程求解 HSV 为什么不使用定义而是使用 Cholesy 和SVD 分解&#xff1f; MATLAB 实践Python 实现 先验知识&#xff1a;可控性 Gramian W c W_c Wc​、可观性 Gramian W o W_o Wo​ 以及 Hankel 奇异值&#xff08;HSV&#xff09; σ i \s…...

机器手电机驱动器小体积解决方案

市场背景 随着工业4.0与人工智能技术的深度融合&#xff0c;智能机器人正加速渗透至医疗、物流、制造及服务等核心领域。据行业分析显示&#xff0c;2023年全球协作机器人市场规模同比增长23%&#xff0c;其中高精度关节驱动与小型化硬件设计成为技术迭代的关键需求。然而&…...

(数智化)采购管理系统平台开发费用

随着招标采购数智化升级加速&#xff0c;采购管理系统平台开发费用成为企业关注的焦点——从几十万到几百万不等&#xff0c;那么开发成本差异的背后藏着怎样的技术逻辑与价值密码呢&#xff1f;采购管理系统研发商郑州信源信息技术股份有限公司根据行业特点及客户实际实践总结…...

K8S Secret 快速开始

一、什么是 Secret&#xff1f; Kubernetes&#xff08;K8s&#xff09;中的 Secret 是一种用于存储和管理敏感信息&#xff08;如密码、令牌、证书、API 密钥等&#xff09;的资源对象。它避免了将敏感数据明文写入配置文件、镜像或代码中&#xff0c;提供了一种更安全的方式…...

TEN:开启实时语音交互的下一代AI Agent引擎

在AI技术飞速发展的今天&#xff0c;语音交互正成为人机交互的重要方式。传统的文本对话已无法满足用户对自然、高效沟通的需求&#xff0c;而TEN开源框架的出现&#xff0c;为开发者提供了构建超低延迟、可听可说的AI Agent的终极解决方案。 一、TEN的核心优势 超低延迟实时交…...

DeepSeek驱动的金市情绪量化:NLP解析贸易政策文本的情绪传导路径

【AI观察】政策信号与市场情绪的量化关联 基于自然语言处理技术对全球财经文本的情绪分析显示&#xff0c;4月30日亚盘时段现货黄金价格波动率较前日下降12.3%&#xff0c;与技术面修正指标呈现强相关性。特政府最新关税政策调整引发市场风险偏好指数&#xff08;RPI&#xff…...

JVM快速入门

目录 前言&#xff1a; 1.JVM的位置 2.JVM的体系结构 3.类加载器 类加载器中的一些方法和细节&#xff1a; 4.双亲委派机制 5.沙箱安全机制 概念 原理 Java 沙箱安全机制 应用场景 6.Native 7.方法区: 8.PC寄存器 9.栈 10.三种JVM HotSpot VM OpenJ9 VM Zin…...

spring--事务详解

spring事务 什么是事务 我们常说的事务&#xff0c;一般指数据库事务。 数据库事务是指 一个逻辑工作单元中执行的一系列&#xff08;数据库操作&#xff09;&#xff0c;要么一起成功&#xff0c;要么一起失败 当工作单元中的所有操作全部正确完成时&#xff0c;工作单元的…...

CSS实现DIV水平与垂直居中方法总结

大家好&#xff0c;欢迎来到程序视点&#xff01;我是你们的老朋友.小二&#xff01; CSS实现DIV水平与垂直居中方法总结 一、水平居中方案 标准方法 .center-div {margin-left: auto;margin-right: auto; }关键点&#xff1a;必须声明DOCTYPE&#xff08;推荐XHTML 1.0 Tran…...