跳到主要内容

2016 年 9 月:新应用

·3 分钟阅读

以下是九月份添加到网站的新 Electron 应用和演讲。


本网站通过社区的 pull requests 更新新的 应用聚会。您可以 watch 该仓库 以获取新添加内容的通知,或者如果您对网站的所有更改不感兴趣,请订阅 博客 RSS feed

如果您制作了 Electron 应用或主持了聚会,请创建一个 pull request 以将其添加到网站,它将进入下一次汇总。

新演讲

九月份,GitHub 举办了 GitHub Universe 大会,该大会被誉为软件未来构建者的盛会。活动中有几个有趣的 Electron 演讲。

此外,如果您在 12 月 5 日恰好在巴黎,Zeke 将在 dotJS 2016 上进行 Electron 演讲

新应用

Pexels搜索完全免费的照片并将它们复制到剪贴板
Timestamp一个更好的 macOS 菜单栏时钟,具有可自定义的日期/时间显示和日历
Harmony与 Spotify、Soundcloud、Play Music 和您的本地文件兼容的音乐播放器
uPhoneWebRTC 桌面电话
SealTalk由 RongCloud IM 云服务和 IM SDK 驱动的即时通讯应用
Infinity一种制作演示文稿的简单方法
Cycligent Git Tool适用于您的 Git 项目的简单、图形化 GUI
Foco使用 Foco 保持专注并提高生产力
Strawberry赢得终身食客,通过一体化餐厅软件套件更好地了解和服务他们。
Mixmax实时查看您电子邮件上的每一个操作。随时随地撰写。
Firebase AdminFirebase 数据管理工具
ANote一个简单友好的 Markdown 笔记
Temps一个简单而智能的菜单栏天气应用
Amium一款将对话带入您文件的工作协作产品
Soube简单的音乐播放器
(Un)colored下一代桌面富内容编辑器,可使用主题 HTML 和 Markdown 兼容性保存文档。适用于 Windows、OS X 和 Linux。
quickcalc菜单栏计算器
Forestpin Analytics面向企业的财务数据分析工具
LingREST 客户端
Shortexts您经常复制的文本、文件夹和表情符号的快捷方式
Front-End Box前端代码生成器集

Electron 的 API 文档作为结构化数据

·3 分钟阅读

今天,我们宣布对 Electron 的文档进行一些改进。每个新版本现在都包含一个 JSON 文件,其中详细描述了 Electron 的所有公共 API。我们创建此文件是为了使开发人员能够以有趣的新方式使用 Electron 的 API 文档。


Schema 概述

每个 API 都是一个对象,具有名称、描述、类型等属性。诸如 BrowserWindowMenu 之类的类具有描述其实例方法、实例属性、实例事件等的附加属性。

以下是描述 BrowserWindow 类的 schema 摘录

{
name: 'BrowserWindow',
description: 'Create and control browser windows.',
process: {
main: true,
renderer: false
},
type: 'Class',
instanceName: 'win',
slug: 'browser-window',
websiteUrl: 'https://electron.js.cn/docs/api/browser-window',
repoUrl: 'https://github.com/electron/electron/blob/v1.4.0/docs/api/browser-window.md',
staticMethods: [...],
instanceMethods: [...],
instanceProperties: [...],
instanceEvents: [...]
}

这是方法描述的示例,在本例中是 apis.BrowserWindow.instanceMethods.setMaximumSize 实例方法

{
name: 'setMaximumSize',
signature: '(width, height)',
description: 'Sets the maximum size of window to width and height.',
parameters: [{
name: 'width',
type: 'Integer'
}, {
name: 'height',
type: 'Integer'
}]
}

使用新数据

为了方便开发人员在其项目中使用此结构化数据,我们创建了 electron-docs-api,这是一个小型 npm 包,每当有新的 Electron 版本发布时,它都会自动发布。

npm install electron-api-docs --save

为了立即获得满足感,请在您的 Node.js REPL 中试用该模块

npm i -g trymodule && trymodule electron-api-docs=apis

数据如何收集

Electron 的 API 文档遵循 Electron 编码风格Electron 风格指南,因此其内容可以进行程序化解析。

electron-docs-linterelectron/electron 仓库的新开发依赖项。它是一个命令行工具,用于检查所有 markdown 文件并强制执行风格指南的规则。如果发现错误,则会列出错误并暂停发布过程。如果 API 文档有效,则会创建 electron-json.api 文件,并作为 Electron 发布的一部分 上传到 GitHub

Standard Javascript 和 Standard Markdown

今年早些时候,Electron 的代码库已更新为对所有 JavaScript 使用 standard linter。Standard 的 README 总结了此选择背后的原因

采用 standard 风格意味着将代码清晰度和社区约定置于个人风格之上。这对于 100% 的项目和开发文化可能没有意义,但是开源对于新手来说可能是一个充满敌意的地方。设置清晰、自动化的贡献者期望使项目更健康。

我们最近还创建了 standard-markdown,以验证我们文档中的所有 JavaScript 代码片段是否有效并与代码库本身的风格一致。

这些工具共同帮助我们使用持续集成 (CI) 来自动查找 pull requests 中的错误。这减轻了人类进行代码审查的负担,并使我们对文档的准确性更有信心。

社区努力

Electron 的文档不断改进,我们感谢我们出色的开源社区为此做出的贡献。截至撰写本文时,已有近 300 人为文档做出了贡献。

我们很高兴看到人们如何使用这种新的结构化数据。可能的用途包括

Electron 内部原理:弱引用

·6 分钟阅读

作为一种具有垃圾回收功能的语言,JavaScript 使用户无需手动管理资源。但是由于 Electron 托管此环境,因此必须非常小心地避免内存和资源泄漏。

这篇文章介绍了弱引用的概念以及它们如何在 Electron 中用于管理资源。


弱引用

在 JavaScript 中,每当您将对象分配给变量时,您都在向该对象添加引用。只要存在对该对象的引用,它将始终保存在内存中。一旦对该对象的所有引用都消失了,即不再有变量存储该对象,JavaScript 引擎将在下一次垃圾回收时回收内存。

弱引用是对对象的引用,它允许您获取对象,而不会影响它是否会被垃圾回收。当对象被垃圾回收时,您也会收到通知。然后,可以使用 JavaScript 管理资源。

以 Electron 中的 NativeImage 类为例,每次调用 nativeImage.create() API 时,都会返回一个 NativeImage 实例,并且它将图像数据存储在 C++ 中。一旦您完成了该实例并且 JavaScript 引擎 (V8) 垃圾回收了该对象,就会调用 C++ 中的代码来释放内存中的图像数据,因此用户无需手动管理它。

另一个例子是 窗口消失问题,它直观地显示了当对窗口的所有引用都消失时,窗口是如何被垃圾回收的。

在 Electron 中测试弱引用

由于该语言没有分配弱引用的方法,因此无法在原始 JavaScript 中直接测试弱引用。JavaScript 中唯一与弱引用相关的 API 是 WeakMap,但由于它仅创建弱引用键,因此无法知道对象何时被垃圾回收。

在 v0.37.8 之前的 Electron 版本中,您可以使用内部 v8Util.setDestructor API 来测试弱引用,该 API 向传递的对象添加弱引用并在对象被垃圾回收时调用回调

// Code below can only run on Electron < v0.37.8.
var v8Util = process.atomBinding('v8_util');

var object = {};
v8Util.setDestructor(object, function () {
console.log('The object is garbage collected');
});

// Remove all references to the object.
object = undefined;
// Manually starts a GC.
gc();
// Console prints "The object is garbage collected".

请注意,您必须使用 --js-flags="--expose_gc" 命令行开关启动 Electron 才能公开内部 gc 函数。

该 API 在更高版本中被删除,因为 V8 实际上不允许在析构函数中运行 JavaScript 代码,并且在更高版本中这样做会导致随机崩溃。

remote 模块中的弱引用

除了使用 C++ 管理原生资源外,Electron 还需弱引用来管理 JavaScript 资源。一个例子是 Electron 的 remote 模块,它是一个 远程过程调用 (RPC) 模块,允许从渲染器进程中使用主进程中的对象。

remote 模块的一个关键挑战是避免内存泄漏。当用户在渲染器进程中获取远程对象时,remote 模块必须保证该对象在主进程中继续存在,直到渲染器进程中的引用消失。此外,它还必须确保当渲染器进程中不再有对该对象的任何引用时,该对象可以被垃圾回收。

例如,如果没有正确的实现,以下代码将很快导致内存泄漏

const { remote } = require('electron');

for (let i = 0; i < 10000; ++i) {
remote.nativeImage.createEmpty();
}

remote 模块中的资源管理很简单。每当请求对象时,都会向主进程发送消息,Electron 会将该对象存储在 map 中并为其分配一个 ID,然后将 ID 发送回渲染器进程。在渲染器进程中,remote 模块将接收 ID 并使用代理对象包装它,并且当代理对象被垃圾回收时,将向主进程发送消息以释放该对象。

remote.require API 为例,简化的实现如下所示

remote.require = function (name) {
// Tell the main process to return the metadata of the module.
const meta = ipcRenderer.sendSync('REQUIRE', name);
// Create a proxy object.
const object = metaToValue(meta);
// Tell the main process to free the object when the proxy object is garbage
// collected.
v8Util.setDestructor(object, function () {
ipcRenderer.send('FREE', meta.id);
});
return object;
};

在主进程中

const map = {};
const id = 0;

ipcMain.on('REQUIRE', function (event, name) {
const object = require(name);
// Add a reference to the object.
map[++id] = object;
// Convert the object to metadata.
event.returnValue = valueToMeta(id, object);
});

ipcMain.on('FREE', function (event, id) {
delete map[id];
});

具有弱值的 Maps

使用之前的简单实现,remote 模块中的每次调用都会从主进程返回一个新的远程对象,并且每个远程对象都表示对主进程中对象的引用。

设计本身很好,但问题是当多次调用接收同一对象时,将创建多个代理对象,对于复杂的对象,这会给内存使用和垃圾回收带来巨大压力。

例如,以下代码

const { remote } = require('electron');

for (let i = 0; i < 10000; ++i) {
remote.getCurrentWindow();
}

它首先使用大量内存创建代理对象,然后占用 CPU(中央处理器)进行垃圾回收并发送 IPC 消息。

一个明显的优化是缓存远程对象:当已经存在具有相同 ID 的远程对象时,将返回之前的远程对象,而不是创建新的远程对象。

这在 JavaScript 核心中的 API 中是不可能的。使用普通 map 缓存对象将阻止 V8 垃圾回收对象,而 WeakMap 类只能使用对象作为弱键。

为了解决这个问题,添加了一种以值作为弱引用的 map 类型,这非常适合缓存具有 ID 的对象。现在 remote.require 看起来像这样

const remoteObjectCache = v8Util.createIDWeakMap()

remote.require = function (name) {
// Tell the main process to return the meta data of the module.
...
if (remoteObjectCache.has(meta.id))
return remoteObjectCache.get(meta.id)
// Create a proxy object.
...
remoteObjectCache.set(meta.id, object)
return object
}

请注意,remoteObjectCache 将对象存储为弱引用,因此无需在对象被垃圾回收时删除键。

原生代码

对于对 Electron 中弱引用的 C++ 代码感兴趣的人,可以在以下文件中找到它

setDestructor API

createIDWeakMap API

2016 年 8 月:新应用

·3 分钟阅读

以下是八月份添加到网站的新 Electron 应用。


本网站通过社区的 pull requests 更新新的 应用聚会。您可以 watch 该仓库 以获取新添加内容的通知,或者如果您对网站的所有更改不感兴趣,请订阅 博客 RSS feed

如果您制作了 Electron 应用或主持了聚会,请创建一个 pull request 以将其添加到网站,它将进入下一次汇总。

新应用

Code RPGifyRPG 风格的编码应用程序
PamFax用于发送和接收传真的跨平台应用
BlankUpMarkdown 编辑器,清晰度 +1
Rambox免费和开源的消息和电子邮件应用,将常见的 Web 应用程序组合为一个
Gordie适用于您的卡片收藏的最佳应用
Ionic Creator更快地构建出色的移动应用
TwitchAlerts使用精美的警报和通知让您的观众满意
Museeks一个简单、干净和跨平台的音乐播放器
SeaPig一个从 markdown 到 html 的转换器
GroupMe非官方 GroupMe 应用
Moeditor您的多用途 markdown 编辑器
SoundnodeSoundnode App 是桌面的 Soundcloud
QMUI WebQMUI Web Desktop 是一个用于管理基于 QMUI Web Framework 的项目的应用程序
Svgsus组织、清理和转换您的 SVG
Ramme非官方 Instagram 桌面应用
InsomniaREST API 客户端
Correo适用于 Windows、macOS 和 Linux 的菜单栏/任务栏 Gmail 应用
KongDashKong Admin API 的桌面客户端
Translation Editor用于 INTL ICU 消息的翻译文件编辑器(请参阅 formatjsio)
5EClient5EPlay CSGO 客户端
Theme Juice轻松进行本地 WordPress 开发

辅助功能工具

·2 分钟阅读

制作可访问的应用程序非常重要,我们很高兴为 DevtronSpectron 引入新功能,使开发人员有机会为每个人更好地制作他们的应用程序。


Electron 应用程序中的辅助功能问题与网站的辅助功能问题类似,因为它们最终都是 HTML。但是,对于 Electron 应用程序,您不能使用在线资源进行辅助功能审核,因为您的应用程序没有 URL 可以指向审核员。

这些新功能将这些审核工具引入您的 Electron 应用程序。您可以选择使用 Spectron 将审核添加到您的测试中,或使用 Devtron 在 DevTools 中使用它们。请继续阅读以了解工具的摘要,或查看我们的 辅助功能文档 以获取更多信息。

Spectron

在测试框架 Spectron 中,您现在可以审核应用程序中的每个窗口和 <webview> 标签。例如

app.client.auditAccessibility().then(function (audit) {
if (audit.failed) {
console.error(audit.message);
}
});

您可以在 Spectron 的文档 中阅读有关此功能的更多信息。

Devtron

在 Devtron 中,有一个新的辅助功能选项卡,可让您审核应用中的页面,对结果进行排序和过滤。

devtron screenshot

这两种工具都使用 Google 为 Chrome 构建的 Accessibility Developer Tools 库。您可以在该 仓库的 wiki 上了解有关此库使用的辅助功能审核规则的更多信息。

如果您知道其他适用于 Electron 的出色辅助功能工具,请通过 pull request 将它们添加到 辅助功能文档 中。

npm install electron

·3 分钟阅读

从 Electron 1.3.1 版本开始,您可以 npm install electron --save-dev 以在您的应用中安装最新的预编译 Electron 版本。


npm install electron

预构建的 Electron 二进制文件

如果您以前使用过 Electron 应用程序,那么您可能已经遇到过 electron-prebuilt npm 包。此包几乎是每个 Electron 项目不可或缺的一部分。安装后,它会检测您的操作系统并下载一个预构建的二进制文件,该文件已编译为可在您系统的架构上运行。

新名称

Electron 安装过程通常是新开发人员的绊脚石。许多勇敢的人试图通过运行 npm install electron 而不是 npm install electron-prebuilt 来开始开发 Electron 应用程序,结果却发现(通常在非常困惑之后)这不是他们正在寻找的 electron

这是因为在 npm 上已经存在一个 electron 项目,该项目是在 GitHub 的 Electron 项目存在之前创建的。为了帮助使 Electron 开发对于新开发人员来说更轻松、更直观,我们联系了现有 electron npm 包的所有者,询问他是否愿意让我们使用该名称。幸运的是,他是我们项目的粉丝,并同意帮助我们重新利用该名称。

Prebuilt 继续存在

从 1.3.1 版本开始,我们已开始同时将 electronelectron-prebuilt 包发布到 npm。这两个包是相同的。我们选择在一段时间内继续以这两个名称发布该包,以免给当前在其项目中使用 electron-prebuilt 的数千名开发人员带来不便。我们建议更新您的 package.json 文件以使用新的 electron 依赖项,但我们将继续发布 electron-prebuilt 的新版本,直到 2016 年底。

electron-userland/electron-prebuilt 仓库将仍然是 electron npm 包的规范主页。

非常感谢

我们要特别感谢 @mafintosh@maxogden 和许多其他 贡献者,感谢他们创建和维护 electron-prebuilt,以及他们为 JavaScript、Node.js 和 Electron 社区提供的不知疲倦的服务。

并感谢 @logicalparadox 允许我们接管 npm 上的 electron 包。

更新您的项目

我们已与社区合作,以更新受此更改影响的流行包。诸如 electron-packagerelectron-rebuildelectron-builder 之类的包已更新为使用新名称,同时继续支持旧名称。

如果您在安装此新包时遇到任何问题,请在 electron-userland/electron-prebuilt 仓库上打开一个 issue 告知我们。

对于 Electron 的任何其他问题,请使用 electron/electron 仓库。

Electron 内部原理:使用 Node 作为库

·4 分钟阅读

这是正在进行的解释 Electron 内部原理的系列文章中的第二篇。如果您还没有阅读,请查看关于事件循环集成的 第一篇文章

大多数人使用 Node 进行服务器端应用程序,但由于 Node 丰富的 API 集和蓬勃发展的社区,它也非常适合作为嵌入式库。这篇文章解释了 Node 如何在 Electron 中用作库。


构建系统

Node 和 Electron 都使用 GYP 作为其构建系统。如果您想在您的应用程序中嵌入 Node,您也必须将其用作您的构建系统。

不熟悉 GYP?在继续阅读本文之前,请阅读 本指南

Node 的标志

Node 源代码目录中的 node.gyp 文件描述了 Node 的构建方式,以及许多 GYP 变量,这些变量控制启用了 Node 的哪些部分以及是否打开某些配置。

要更改构建标志,您需要在项目的 .gypi 文件中设置变量。Node 中的 configure 脚本可以为您生成一些常用配置,例如运行 ./configure --shared 将生成一个 config.gypi,其中包含指示 Node 构建为共享库的变量。

Electron 不使用 configure 脚本,因为它有自己的构建脚本。Node 的配置定义在 Electron 根源代码目录下的 common.gypi 文件中。

在 Electron 中,Node 被链接为共享库,这是通过将 GYP 变量 node_shared 设置为 true 来实现的。因此,Node 的构建类型将从 executable 更改为 shared_library,并且包含 Node main 入口点的源代码将不会被编译。

由于 Electron 使用 Chromium 附带的 V8 库,因此 Node 源代码中包含的 V8 库不会被使用。这是通过将 node_use_v8_platformnode_use_bundled_v8 都设置为 false 来实现的。

共享库或静态库

当与 Node 链接时,有两种选择:您可以将 Node 构建为静态库并将其包含在最终可执行文件中,或者您可以将其构建为共享库并与最终可执行文件一起发布。

在 Electron 中,Node 长期以来都是作为静态库构建的。这使得构建过程简单,实现了最佳的编译器优化,并允许 Electron 在分发时无需额外的 node.dll 文件。

然而,在 Chrome 切换到使用 BoringSSL 后,这种情况发生了改变。BoringSSL 是 OpenSSL 的一个分支,它移除了几个未使用的 API 并更改了许多现有的接口。由于 Node 仍然使用 OpenSSL,如果它们被链接在一起,编译器将由于符号冲突而生成大量的链接错误。

Electron 无法在 Node 中使用 BoringSSL,也无法在 Chromium 中使用 OpenSSL,因此唯一的选择是切换到将 Node 构建为共享库,并在每个组件中 隐藏 BoringSSL 和 OpenSSL 符号

这一改变为 Electron 带来了一些积极的副作用。在此更改之前,如果您使用了原生模块,则无法在 Windows 上重命名 Electron 的可执行文件,因为可执行文件的名称被硬编码在导入库中。在 Node 被构建为共享库之后,这个限制消失了,因为所有原生模块都链接到 node.dll,而 node.dll 的名称不需要更改。

支持原生模块

Node 中的 原生模块 的工作原理是定义一个入口函数供 Node 加载,然后从 Node 中搜索 V8 和 libuv 的符号。这对嵌入者来说有点麻烦,因为默认情况下,当将 Node 构建为库时,V8 和 libuv 的符号是隐藏的,原生模块将无法加载,因为它们找不到这些符号。

因此,为了使原生模块工作,V8 和 libuv 的符号在 Electron 中被暴露出来。对于 V8,这是通过 强制 Chromium 配置文件中所有符号都暴露出来 来实现的。对于 libuv,这是通过 设置 BUILDING_UV_SHARED=1 定义 来实现的。

在你的应用中启动 Node

在完成所有构建和链接 Node 的工作之后,最后一步是在你的应用中运行 Node。

Node 没有提供很多用于将其嵌入到其他应用的公共 API。通常,您只需调用 node::Startnode::Init 即可启动一个新的 Node 实例。但是,如果您正在构建一个基于 Node 的复杂应用,则必须使用像 node::CreateEnvironment 这样的 API 来精确控制每个步骤。

在 Electron 中,Node 以两种模式启动:运行在主进程中的独立模式(类似于官方 Node 二进制文件)和将 Node API 插入到网页中的嵌入模式。这些细节将在以后的文章中解释。

2016 年 7 月:新应用和聚会

·2 分钟阅读

我们正在开始一个每月综述,以突出 Electron 社区的活动。每个综述将包含新应用、即将到来的聚会、工具、视频等等。


本网站通过社区的 pull requests 更新新的 应用聚会。您可以 watch 该仓库 以获取新添加内容的通知,或者如果您对网站的所有更改不感兴趣,请订阅 博客 RSS feed

如果您制作了 Electron 应用或主持了聚会,请创建一个 pull request 以将其添加到网站,它将进入下一次汇总。

新应用

Demio一个为入站销售和营销构建的网络研讨会平台
ElectorrentuTorrent 服务器的远程客户端应用
PhoneGap这个开源框架让您可以使用 Web 技术构建出色的移动应用
WordMark一个轻量级的博客发布编辑器,适用于 Markdown 作者
UbAuth帮助开发者使用 OAuth 2.0 为 Uber 应用创建访问令牌的应用
HyperTermHTML/JS/CSS 终端
MarpMarkdown 演示文稿编写器
Glyphr Studio一个免费的、基于 Web 的字体设计器,专注于为爱好者进行字体设计
BitCrypt一个简单的 Windows 文件加密应用程序,加密你的数据位
Trym美丽的小型 macOS 应用,可帮助您查看、优化和转换 SVG 图标
Booker具有 Markdown 功能的文本编辑器
PhonePresenter最智能的演示文稿点击器
Yout在桌面上观看 YouTube 播放列表的新方式

新的聚会

Electron 开源桌面框架英国,伦敦

Electron 内部原理:消息循环集成

·3 分钟阅读

这是解释 Electron 内部原理系列文章的第一篇。这篇文章介绍了 Node 的事件循环是如何在 Electron 中与 Chromium 集成的。


之前有很多尝试使用 Node 进行 GUI 编程,例如用于 GTK+ 绑定的 node-gui 和用于 QT 绑定的 node-qt。但是它们都不能在生产环境中使用,因为 GUI 工具包有自己的消息循环,而 Node 使用 libuv 作为其自身的事件循环,并且主线程一次只能运行一个循环。因此,在 Node 中运行 GUI 消息循环的常见技巧是在一个非常小的时间间隔内使用计时器泵送消息循环,这使得 GUI 界面响应缓慢并占用大量 CPU 资源。

在 Electron 的开发过程中,我们遇到了同样的问题,尽管是以相反的方式:我们必须将 Node 的事件循环集成到 Chromium 的消息循环中。

主进程和渲染进程

在我们深入研究消息循环集成的细节之前,我将首先解释 Chromium 的多进程架构。

在 Electron 中,有两种类型的进程:主进程和渲染进程(实际上这非常简化,要获得完整的视图,请参阅 多进程架构)。主进程负责 GUI 工作,例如创建窗口,而渲染进程仅处理运行和渲染网页。

Electron 允许使用 JavaScript 来控制主进程和渲染进程,这意味着我们必须将 Node 集成到这两个进程中。

用 libuv 替换 Chromium 的消息循环

我的第一次尝试是用 libuv 重新实现 Chromium 的消息循环。

对于渲染进程来说这很容易,因为它的消息循环只监听文件描述符和计时器,而我只需要实现与 libuv 的接口。

然而,对于主进程来说,这要困难得多。每个平台都有自己类型的 GUI 消息循环。macOS Chromium 使用 NSRunLoop,而 Linux 使用 glib。我尝试了很多技巧来从原生 GUI 消息循环中提取底层文件描述符,然后将它们馈送到 libuv 进行迭代,但我仍然遇到了不起作用的边缘情况。

所以最后我添加了一个计时器,以小间隔轮询 GUI 消息循环。结果,该进程占用了恒定的 CPU 使用率,并且某些操作有很长的延迟。

在单独的线程中轮询 Node 的事件循环

随着 libuv 的成熟,那时可以采取另一种方法。

后端 fd 的概念被引入到 libuv 中,它是一个文件描述符(或句柄),libuv 为其事件循环轮询它。因此,通过轮询后端 fd,可以在 libuv 中有新事件时收到通知。

因此,在 Electron 中,我创建了一个单独的线程来轮询后端 fd,并且由于我使用的是系统调用进行轮询而不是 libuv API,因此它是线程安全的。每当 libuv 的事件循环中出现新事件时,都会向 Chromium 的消息循环发布一条消息,然后 libuv 的事件将在主线程中处理。

通过这种方式,我避免了修补 Chromium 和 Node,并且相同的代码被用于主进程和渲染进程。

代码

你可以在 electron/atom/common/ 下的 node_bindings 文件中找到消息循环集成的实现。它可以很容易地被想要集成 Node 的项目重用。

更新:实现已移动到 electron/shell/common/node_bindings.cc

Electron 播客

·一分钟阅读

正在寻找 Electron 的介绍?刚刚发布了两个新的播客,它们对 Electron 是什么、为什么构建以及如何使用进行了很好的概述。


现已发布

Hanselminutes:创建跨平台 Electron 应用

Electron 仅仅是“框架中的 Chrome”还是远不止于此?Jessica 将 Scott 引导到正确的方向,并准确解释了 Electron 平台在您的开发世界中的位置。


JavaScript Air:Electron 应用

Electron 正变得越来越流行和相关,成为使用 Web 技术构建多平台桌面应用的方式。让我们深入了解这项出色的技术,看看我们如何使用它来增强我们自己的体验以及用户在桌面上的体验。


如果您正在寻找 Electron 的介绍,请收听第一个播客。第二个播客更详细地介绍了如何构建应用,并提供了来自 Nylas 的 Evan Morikawa 的宝贵技巧。

我们目前正在制作另外两个播客,预计下个月发布,请关注 @ElectronJS Twitter 帐户以获取更新。