2024.02.20

优化的数据支撑

升级流程优化,APP刷新耗时

项目中比较核心、重要的地方,有技术挑战的

WebSocket

WebSocket是一种在客户端和服务端之间建立双向通信的连接,它可以实现实时的数据传输,避免了HTTP协议中频繁的请求和响应,从而提高了web应用程序的性能和用户体验。

与HTTP的区别
是两种不同的协议

  • 连接方式:HTTP是基于请求和响应的模式,客户端每次获取数据都需要发送一个新的HTTP请求,而Websocket是全双工的,在客户端和服务端建立好一次连接后,就可以随时发送数据
  • 数据格式:HTTP协议传输的数据一般采用JSON、XML等格式进行封装,而WebSocket协议则可以直接传输二进制数据。
  • 通信效率:HTTP协议中每次数据传输都需要经过请求和响应的过程,而WebSocket协议则避免了这种重复的过程,可以实现更加高效的实时通信。
  • 安全性:HTTP协议的安全性依赖于SSL/TLS协议,而WebSocket协议本身也支持SSL/TLS加密,可以提供更好的安全保障。
    WebSocket是否存在跨域问题
    WebSocket也存在跨域问题,当浏览器从一个域名的页面下向另一个域名的服务器发起WebSocket连接时,就会涉及到跨域问题。WebSocket协议并没有同源协议的限制,但是在建立WebSocket连接时需要通过HTTP协议进行握手,这个过程需要遵循同源策略。通过CORS跨域方式进行连接。
    如何确保Websocket是连接状态
    心跳机制: 我们实施了定时的心跳机制,周期性地向服务器发送心跳消息,确保连接保持活跃。这有效防止了连接被自动关闭,提高了连接的可靠性。
// 定时向服务器发送心跳消息
    // 设置定时器,每隔30秒执行一次指定的回调函数
    setInterval(() => {
        // 检查 WebSocket 连接的当前状态是否为 OPEN
        if (connection.readyState === WebSocket.OPEN) {
            // 如果连接处于 OPEN 状态,则通过连接对象发送心跳消息 'heartbeat'
            connection.send('heartbeat');
        }
    }, 30000); // 每 30 秒发送一次心跳

// 创建ws连接 https
var ws = new WebSocket("wss://echo.websocket.org");

消息不一致如何处理

如何理解Electron

Electron是一个前端框架,用于构建跨平台的桌面端应用,且这些应用可以在不同的系统上运行,实现了跨平台开发。简单来说就是通过前端技术写了个web应用,套了Electron的壳子,就变成了桌面端应用。

Electron进程,通信方式

主进程和渲染进程
主进程:一个项目有且只有一个主进程,创建窗口等有关系统事件写在主进程中进行。Electron项目启动的时候运行main.js的进程就是主进程。
渲染进程:index.html页面运行在渲染进程,创建一个窗体就会创建一个渲染进程,每个web页面运行在自己的渲染进程中,每个渲染进程是独立的。每个BrowserWindow实例都运行在自己的渲染进程中,当BrowserWindow实例被销毁后,相应的渲染进程终止。
进程间通信:
1. 渲染进程–>主进程(单向)
使用ipcRenderer.send API 发送消息,使用ipcRenderer.on API 接收消息,一般用在Web向主进程发送消息
2. 渲染进程–>主进程(双向)
双向 IPC 的一个常见应用是从渲染器进程代码调用主进程模块并等待结果。 这可以通过将 ipcRenderer.invoke 与 ipcMain.handle 搭配使用来完成。渲染进程发送 ipcRenderer.invoke消息时,主进程通过ipcMain.handle返回一个回调。
3. 主进程–>渲染进程(双向)
消息从主进程发到渲染进程时,需要知道是哪一个渲染进程,消息需要通过其webcontents实例发送到渲染进程,此实例包含一个send方法,使用方法和ipcRenderer.send相同。
4. 渲染进程–>渲染进程
没有直接的方法可以使用 ipcMain 和 ipcRenderer 模块在 Electron 中的渲染器进程之间发送消息。将主进程作为渲染器之间的消息代理。 这需要将消息从一个渲染器发送到主进程,然后主进程将消息转发到另一个渲染器。

Electron中的preload.js是干啥的?

使用预加载脚本来安全地将特权 API 暴露至渲染进程中。

Electron 的主进程是一个拥有着完全操作系统访问权限的 Node.js 环境。 除了 Electron 模组 之外,您也可以访问 Node.js 内置模块 和所有通过 npm 安装的包。 另一方面,出于安全原因,渲染进程默认跑在网页页面上,而并非 Node.js里。
为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为 预加载 的特殊脚本。

预加载脚本包含在浏览器窗口加载网页之前运行的代码。 其可访问 DOM 接口和 Node.js 环境,并且经常在其中使用 contextBridge 接口将特权接口暴露给渲染器。

由于主进程和渲染进程有着完全不同的分工,Electron 应用通常使用预加载脚本来设置进程间通信 (IPC) 接口以在两种进程之间传输任意信息。

判断一个对象是否为空对象

  1. 通过JSON.stringify将对象转为字符串,判断转换之后的结果是否等于“{}”;
  2. 通过for in遍历对象,如果走到循环内,则返回false,表示不是空对象,否则是空对象;
  3. Object.getOwnPropertyNames()方法,该方法可以获取到对象的属性名,并将其存入数组中,根据数组长度判断对象是否为空;
  4. ES6新方法Object.keys(),返回属性名组成的数组,根据长度判断是否为空对象。

JSON.Stringify弊端,什么不能复制

  1. 无法处理循环引用,如果被拷贝的对象中存在循环饮用,比如对象A中的属性引用了对象B,对象B中的属性引用的对象A,那么JSON.Stringify会抛出异常;
  2. 无法拷贝一些特殊对象,例如函数,正则表达式,日期对象等;
  3. 无法拷贝对象的非枚举类型,对于不可枚举属性和Symbol类型的属性,会被忽略;
  4. 会忽略 undefined、函数以及 symbol 类型的属性,导致拷贝后的对象丢失这些属性。

深拷贝

const deepClone = (obj, cache = new WeakMap()) => {
    if(obj === null || typeof obj !== 'object') {
        return obj;
    }
    if(obj instanceof Date) {
        return new Date(obj);
    }
    if(obj instanceof RegExp) {
        return new RegExp(obj);
    }
    // 4.Symbol类型
    if (typeof obj === 'symbol') {
        // 返回一个新的Symbol,并且将其描述传递过去
        return Symbol(obj.description)
    }
    if(cache.has(obj)) {
        return cache.get(obj);
    }
    let cloneObj = Array.isArray(obj) ? [] : {};
    // let cloneObj = new obj.constructor();// 使用对象所属的构造函数创建一个新对象
    cache.set(obj, cloneObj);
    for(let key in obj) {
        if(obj.hasOwnProperty(key)) {
            cloneObj[key] = deepClone(obj[key], cache);
        }
    }
    return cloneObj;
}
const symbolName = Symbol('1');
const obj = {
	number: 1,
	string: 'stirng',
	objRegexp: new RegExp('\\w'),
	regexp: /w+/g,
	date: new Date(),
	array: [{a: 1}, 2],
	symbolName: 111
}
// obj.a = obj // 循环引用
const newObj = deepClone(obj)
console.log(newObj, obj, newObj.objRegexp,obj.objRegexp)

普通函数与箭头函数的区别,获取形参的方法

区别:

  1. 普通函数可以是具名函数也可以是匿名函数,箭头函数只能是匿名函数;
  2. 普通函数的this指向指向调用它的对象,箭头函数没有自己的this对象,它的this指向在定义时就确定了,永远指向它定义时上层作用域的this,普通函数可以通过call、apply、bind改变this指向,箭头函数不可以;
  3. 箭头函数没有原型,不能当作构造函数;
  4. 普通函数能够通过arguments来获取形参,箭头函数不可以,其自身没有arguments,箭头函数可以通过剩余运算符(…)来获取,普通函数也可以通过此方法获取,通过剩余运算符获取的参数是一个数组,而通过arguments获取的是类数组;

闭包是什么,闭包的应用

闭包简单理解就是函数嵌套函数,内部函数可以访问外部函数的变量。

闭包的应用:

  1. 防抖、节流;
  2. 模拟私有属性;
  3. 回调函数;

闭包会导致内存泄漏吗,怎么使用会导致内存泄漏

闭包本身不会导致内存泄漏

var scope = "window";
function checkscope(){
	var scope ="local".
	function f(){
		return scope;
	}
	return f;
}
var foo = checkscope();//会导致
foo();
// foo = undefined; //添加这一行释放内存
//foo();
checkscope()();//不会导致
  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值