在大中型项目开发中,介于 js 孱弱的安全加密功能,通常都会结合 node addon 来进行开发,保护代码安全(相对的)。那么在应用退出时,有需要 node addon 执行清理任务,这时的时机是何时比较好,本文在此梳理下。
废话不多说,先上图.
接下来,我们先分析下 electron 应用退出的触发点(如何退出)。
1、点击 x 按钮退出
如果我们使用 electron 提供(平台相关)的 BrowserWindow 样式,未做修改,那么在 linux/windows 点击 x 按钮即退出了应用。在 electron 的 demo 中会看到这样的代码
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
表示 macOS 点击 x 按钮不退出应用,这是符合 macOS 平台的应用特性,稍后再表。
2、有时为了UI统一或者特殊的样式处理,抛弃了原生提供的窗口控制按钮
这时候就需要调用 electron 提供的 api 实现退出逻辑:app.quit()/app.exit([exitCode])
如上图所示,当触发退出时,electron 的生命周期如何调用。
着重说下 app.quit() 和 app.exit([code])
的区别
app.quit()
: 此方法尝试关闭所有窗口(如果窗口有 window.on('close', (e) => e.preventDefault()) 则失败)。- 首先发出
before-quit
事件,如果所有窗口关闭成功,则发出will-quit
事件,然后 app 退出。 - 此方法会确保执行所有的
beforeunload
和unload
(dom)事件,当然可以在beforeunload
事件中返回 false 阻止继续退出。
- 首先发出
app.exit([exitCode])
: 使用exitCode
立即退出。exitCode
默认为0。- 所有窗口立即关闭,而不询问用户,且不触发
beforeunload
和unload
事件。
- 所有窗口立即关闭,而不询问用户,且不触发
因为我们需要执行阻止默认退出的逻辑,所以此处需要使用
app.quit()
自定义窗口控制按钮
首先,最常见的是有需要在 macOS 上点击 x 执行的是最小化指令,如 demo 所示。然后是最小化、最大化调用普通方法就行。不过有个坑点,最大化 maxium 时候,不能再动态调整窗口大小了,否则再次调用时就会有非预期的情况出现。
多窗口时关闭主窗口
默认会关闭所有窗口,然后调用 win.on('window-all-closed)
事件,这时,如上 demo 所示,macOS 不会退出应用,如果点击 dock 栏图标,会再次重新创建主窗口。
执行清理任务
当用户触发关闭操作时,应该先快速响应主窗口关闭,可以提高用户体验,不致有 app 卡顿的印象。所以不适宜在 window.close()/window.closed()
事件中处理。
如上图所示,只能在 app.will-quit
中处理.
let canQuitNow = false
app.on('will-quit', async (e) => {
console.log('[app] will-quit')
if (!canQuitNow) {
e.preventDefault()
await doClean()
canQuitNow = true
app.quit()
}
})
async function doClean() {
return new Promise((resolve) => {
setTimeout(() => {
// ... heavy operation
resolve()
}, 1000)
})
}
Enjoy Coding!😊