Electron 退出时的生命周期

3,375 阅读2分钟

在大中型项目开发中,介于 js 孱弱的安全加密功能,通常都会结合 node addon 来进行开发,保护代码安全(相对的)。那么在应用退出时,有需要 node addon 执行清理任务,这时的时机是何时比较好,本文在此梳理下。

废话不多说,先上图.

electron quit logic.png

接下来,我们先分析下 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统一或者特殊的样式处理,抛弃了原生提供的窗口控制按钮

image.png 这时候就需要调用 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 退出。
    • 此方法会确保执行所有的 beforeunloadunload(dom)事件,当然可以在 beforeunload 事件中返回 false 阻止继续退出。
  • app.exit([exitCode]): 使用 exitCode 立即退出。exitCode 默认为0。
    • 所有窗口立即关闭,而不询问用户,且不触发 beforeunloadunload 事件。

因为我们需要执行阻止默认退出的逻辑,所以此处需要使用 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!😊