安装node.js
安装
验证
其他设置1
镜像
- 找到
npm
配置文件:Windows
:C:\Users\<用户名>\.npmrc
Mac/Linux
:~/.npmrc
- 用文本编辑器打开
.npmrc
,添加以下内容:
- 保存文件并重启终端
- 清理缓存并重试
- 可能需要
- 通过以下命令检查配置是否生效:
electron_mirror=https://npmmirror.com/mirrors/electron/
表示配置成功
代理
- 若使用
VPN
或企业代理,需在.npmrc
中添加代理设置:
创建应用程序
初始化 npm
项目
将 Electron
安装为项目的 devDependencies
- 仅在开发环境需要的额外依赖
- 输出如下:
运行 Electron
应用
main.js
package.json
- 要执行这个脚本,需要在
package.json
的scripts
字段中添加一个start
命令,内容为electron .
- 这个命令会告诉
Electron
在当前目录下寻找主脚本,并以开发模式运行它
- 要执行这个脚本,需要在
- 终端执行:
将网页装载到 BrowserWindow
- 在
Electron
中,每个窗口展示一个页面,后者可以来自本地的HTML
,也可以来自远程URL
- 在项目的根目录中创建一个
index.html
文件,并写入下面的内容:
- 在项目的根目录中创建一个
修改main.js
- 第一行中,我们使用
CommonJS
语法导入了两个Electron
模块:app
,这个模块控制着您应用程序的事件生命周期BrowserWindow
,这个模块创建和管理app
的窗口
Electron
的许多核心模块都是Node.js
的事件触发器,遵循Node.js
的异步事件驱动架构app
模块就是其中一个- 在
Electron
中,只有在app
模块的ready
事件(event
)触发后才能创建BrowserWindows
实例 - 可以通过使用
app.whenReady()
API
来监听此事件,并在其成功后调用createWindow()
方法
关于页面
- 应用中的每个页面都在一个单独的进程中运行,我们称这些进程为 渲染器 (
renderer
) - 渲染进程使用与常规
Web
开发相同的JavaScript API
和工具
管理应用的窗口生命周期
概述
- 应用窗口在不同操作系统中的行为也不同
Electron
允许您自行实现这些行为来遵循操作系统的规范,而不是采用默认的强制执行- 可以通过监听
app
和BrowserWindow
模组的事件,自行实现基础的应用窗口规范
针对特定平台
- 通过检查
Node.js
的process.platform
变量,您可以针对特定平台运行特定代码
关闭所有窗口时退出应用 (Windows & Linux
)
- 在
Windows
和Linux
上,我们通常希望在关闭一个应用的所有窗口后让它退出 - 可以监听
app
模块的window-all-closed
事件,并在判断用户不使用macOS
后调用app.quit()
来退出您的应用程序
没有窗口打开则打开一个窗口 (macOS
)
- 与前二者相比,即使没有打开任何窗口,
macOS
应用通常也会继续运行- 在没有窗口可用时调用
app
会打开一个新窗口 - 可以监听
app
模组的activate
事件,如果没有任何打开(open
)的BrowserWindow
,调用您已有的createWindow()
方法新建一个
- 在没有窗口可用时调用
VSCode
里面调试
- 在根目录新建一个
.vscode
文件夹,然后在其中新建一个launch.json
配置文件并填写如下内容
DevTools
调试
Node.js
的异步事件驱动架构
概述
Node.js
的异步事件驱动架构是其高效处理高并发的核心机制,结合了非阻塞I/O
、事件循环(Event Loop
)和事件驱动的编程模型
V8
- 负责解析和执行
JavaScript
代码,将代码编译为机器指令 - 与底层系统直接交互,提升性能
libuv
库
- 跨平台异步
I/O
库,提供事件循环、线程池和文件系统操作的非阻塞实现 - 管理事件循环的
6
个阶段(timers
、poll
、check
等),协调异步任务调度
事件循环(Event Loop
)
- 单线程模型:
- 主线程仅负责事件调度,避免多线程上下文切换的开销
- 非阻塞
I/O
:- 通过回调函数或
Promise
处理耗时操作(如文件读写、网络请求),主线程无需等待I/O
完成
- 通过回调函数或
事件循环的详细阶段
- 概述
- 事件循环按顺序执行以下阶段,每个阶段处理特定类型的任务
Timers
阶段- 执行
setTimeout
和setInterval
的回调
- 执行
Pending I/O Callbacks
- 处理上一轮未完成的
I/O
回调(如TCP
错误)
- 处理上一轮未完成的
Idle/Prepare
- 系统内部使用
Poll
阶段- 核心阶段:检索新的
I/O
事件(如文件读取完成、HTTP
请求到达),执行关联的回调 - 若队列为空,则阻塞等待新事件,或跳转到
Check
阶段
- 核心阶段:检索新的
Check
阶段- 执行
setImmediate
的回调
- 执行
Close Callbacks
- 处理关闭事件(如
socket.on('close')
)
- 处理关闭事件(如
异步任务的分类与优先级
- 宏任务(
Macrotask
)- 包括
setTimeout
、setInterval
、I/O
操作、setImmediate
- 每个事件循环阶段执行一个宏任务
- 包括
- 微任务(
Microtask
)- 包括
Promise.then
、process.nextTick
process.nextTick
在事件循环各阶段之间立即执行(优先级最高)Promise
回调在宏任务结束后执行
- 包括
事件驱动模型的核心机制
EventEmitter
类- 实现发布-订阅模式,通过
.on()
注册事件监听器,.emit()
触发事件
- 实现发布-订阅模式,通过
非阻塞 I/O
的工作流程
- 主线程发起
I/O
请求后,立即继续执行后续代码 I/O
完成后,libuv
将回调推入事件队列,事件循环在Poll
阶段执行回调
单线程与事件循环
Node.js
主线程运行V8
引擎解析JavaScript
,同步代码直接执行,异步任务(如I/O
、定时器)通过libuv
提交到事件循环队列- 主线程通过 事件循环(
Event Loop
) 调度任务,避免阻塞
- 主线程通过 事件循环(
- 与
libuv
的协作- 任务分发:
Node.js
主线程将异步任务(如fs.readFile
)委托给libuv
,后者通过线程池或系统内核的异步接口(如epoll
)处理 - 回调触发:任务完成后,
libuv
将回调推入事件队列,主线程在轮询到对应阶段时执行回调
- 任务分发:
问题
libuv
是否维护自己的事件队列?- 是的,
libuv
维护独立的事件队列,但它的队列结构是分阶段的 libuv
的事件循环分为6
个阶段(如Timers
阶段、Poll
阶段、Check
阶段等),每个阶段对应一个特定类型的事件队列
Timers
队列:存放setTimeout
/setInterval
的回调
I/O
队列:存放已完成的I/O
操作(如文件读写、网络请求)的回调
Check
队列:存放setImmediate
的回调- 当异步任务(如文件
I/O
)完成时,libuv
的线程池会将回调推入对应阶段的队列,等待事件循环轮询到该阶段时执行
- 是的,
- 主线程是否有自己的事件队列?
- 主线程没有独立的事件队列,但
Node.js
主线程的事件循环与libuv
的事件队列紧密绑定
具体来说:
主线程的事件循环直接管理libuv
的事件队列
当主线程空闲时,会通过事件循环(uv_run
)依次轮询libuv
的6
个阶段队列,并执行其中的回调 - 微任务队列:主线程还有两个特殊的中间队列(不属于
libuv
):
nextTick
队列:存放process.nextTick
的回调,优先级最高
Microtask
队列:存放Promise
的回调,优先级次之
这两个队列会在每个libuv
阶段切换时优先清空
- 主线程没有独立的事件队列,但
- 主线程有没有任务队列?
nextTick 队列
和Microtask 队列
属于Node.js
主线程自身的任务队列
- 回调的执行者是
libuv
还是主线程?- 回调由主线程执行,但
libuv
负责调度: libuv
线程池:处理耗时任务(如文件I/O
、DNS
解析),完成后将回调推入对应阶段的队列- 主线程的事件循环:在轮询到对应阶段时,从
libuv
队列中取出回调并执行
- 回调由主线程执行,但
- 主程序处理任务的优先级?
- 同步代码
nextTick
队列Microtask
队列libuv
阶段队列(如Timers
、I/O
)
总结(记忆)
node.js
主线程运行着一个事件循环,还有两个自己的任务队列nextTick
和Microtask
v8
引擎负责解析执行JavaScript
代码,同步代码直接在主线程执行,异步代码交给libuv
处理libuv
维护了6
个阶段队列,这6
个队列存放相应任务的对应的回调node.js
主线程在空闲时候,按优先级取出这些队列中的回调(nextTick
,Microtask
,libuv
阶段队列)并执行
事件触发器
EventEmitter
类
Node.js
的events
模块提供了EventEmitter
类,所有能触发事件的对象均是该类的实例- 通过
on()
方法注册监听器(订阅事件),emit()
方法触发事件(发布事件)
事件驱动的异步模型
- 异步模型见上述
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
热评文章
- * 暂无