Electron自動更新失效報錯Error:?Object?has?been?destroyed的問題解決
Electron 自動更新失敗
在 Electron 應(yīng)用某次更新,出現(xiàn)了如下循環(huán)更新的問題:
此時,查詢?nèi)罩荆l(fā)現(xiàn)報錯如下 Error: Object has been destroyed
:
問題原因
首先,通過查閱資料得知:在 Electron 中,當(dāng)一個窗口被銷毀后,與該窗口相關(guān)聯(lián)的 JavaScript 對象也會被銷毀,如果再次嘗試訪問已被銷毀的窗口對象時,就會發(fā)出上圖所示的錯誤。
通過日志可以很好的找到問題發(fā)生的地方(幸好我們主進程中關(guān)鍵點都添加了明顯的日志信息,方便問題查找),很明顯是在 autoUpdater.on('update-available'
檢測到自動更新后的報錯,那就著重排查下這里。
autoUpdater.on('update-available', () => { mainLogger.info('自動更新 有新版本') disableStopMainWindowClose() win.show() mainWindow.destroy() })
通過日志可以分析應(yīng)該是在 disableStopMainWindowClose
方法中的產(chǎn)生的問題:
export function disableStopMainWindowClose() { mainWindow.off('close', onMainClose) systemStatus.off() } function onMainClose(e: Electron.Event) { if (isQuit) return if (mainWindow.isFullScreen()) { ... }
如何解決
為了避免這個錯誤,需要在窗口對象被銷毀時取消訂閱所有與該窗口相關(guān)的事件,并在需要訪問窗口對象時先檢查窗口對象是否已經(jīng)被銷毀。
所以需要在調(diào)用窗口方法前,先判斷窗口是否已被銷毀
function onMainClose(e: Electron.Event) { if (isQuit) return if (!mainWindow?.isDestroyed()) return ...
重新打包,上傳成功后,再次出發(fā)自動更新,即可正常了。順便說一下我們 Electron 應(yīng)用的更新流程。
打包
首先是打包,打包時需要更新 package.json 中的版本和說明
{ "version": "2.2.7", "versionNotes": "發(fā)現(xiàn)新版本 v2.2.7!\n\n1. 修復(fù)客服已知問題" }
修改完后,Mac 和 Windows 各自打包,并上傳到服務(wù)器。
自動更新流程
關(guān)于 Electron 應(yīng)用的自動更新,官方提供了更新應(yīng)用程序處理自動更新過程。
因為我們使用的 electron-builder 打包應(yīng)用,所以使用的是它內(nèi)置的更新程序Auto Update。
相比 Electron 中自帶的更新,它有以下優(yōu)勢:
- 不需要搭建專用的發(fā)布服務(wù)器,可上傳到任意服務(wù)器;
- 代碼簽名驗證可以在 macOS 和 Windows 上進行;
- 支持下載進度提示;
- 代碼簡單,工作量少。
實現(xiàn)過程
安裝依賴
yarn add electron-updater
主窗口調(diào)用
當(dāng)主窗口被激活顯示時,通過 checkLatestVersion
方法檢查是否有版本更新
mainWindow.on('show', checkLatestVersion)
檢測是否有更新
checkLatestVersion
方法定義在主進程的 update.ts 文件中
// update.ts ... export const checkLatestVersion = () => { getLatestVersionInfo().then((version: any) => { if (!version) return mainLogger.info('檢查最新版本', version) dialog .showMessageBox(mainWindow, { defaultId: 0, cancelId: 3, message: version.notes, buttons: version.isCurrVersionAvailable ? ['更新', '取消'] : ['更新'], }) .then(({ response }) => response === 0) .then((isUpdate) => { if (isUpdate) IS_MAC ? checkMacUpdate() : checkWinUpdate() }) .finally(() => (isDialogOpen = false)) }) }
getLatestVersionInfo
方法用于檢測更新,主要通過比對服務(wù)器的安裝包版本是否大于本地版本,在本地打完包后,會將本地的包上傳到服務(wù)器上,同時會有一份 RELEASE.json
文件,就是通過比對 RELEASE.json
文件中的 currentRelease
字段。
{ "currentRelease": "2.2.7", "notes": "發(fā)現(xiàn)新版本 v2.2.7!\n\n1. 修復(fù)客服已知問題。" }
當(dāng)大于本地版本即需要更新時,顯示更新窗口(包含更新版本、更新說明等),當(dāng)用戶點擊更新
后,調(diào)用 Mac 或 Windows 的更新方法。
檢查更新前奏——創(chuàng)建更新窗口
const checkMacUpdate = () => { const win = createAutoUpdateWindow() ... }
首先通過 createAutoUpdateWindow
創(chuàng)建更新窗口
const createAutoUpdateWindow = () => { const win = new BrowserWindow({ width: 560, height: 120, titleBarStyle: 'hidden', webPreferences: { preload: path.join(__dirname, 'preload.js'), }, }) win.loadURL(getLocalUrl('/auto-update')) return win }
上面代碼中創(chuàng)建了一個瀏覽器窗口,并加載 /auto-update
路由:
<template> <section style="padding: 42px 32px"> <a-progress :show-info="false" :stroke-color="{ '0%': '#108ee9', '100%': '#87d068' }" :percent="percent" status="active" /> <center style="padding-top: 16px">正在更新中,更新完成后會自動重啟,請耐心等待。</center> </section> </template> <script setup> import { onMounted, ref } from 'vue' const percent = ref(0) const timer = setInterval(() => { percent.value += 2 if (percent.value >= 95) clearInterval(timer) }, 300) </script>
頁面顯示一個假的進度條即可,新版本下載完成后會自動關(guān)閉并安裝。
autoUpdater 自動更新
const checkMacUpdate = () => { const win = createAutoUpdateWindow() // 監(jiān)聽升級失敗事件 autoUpdater.on('error', (message) => { mainLogger.error('自動更新', message) }) // 監(jiān)聽發(fā)現(xiàn)可用更新事件 autoUpdater.on('update-available', () => { mainLogger.info('自動更新 有新版本') isUpdating = true disableStopMainWindowClose() win.show() mainWindow.destroy() }) // 監(jiān)聽沒有可用更新事件 autoUpdater.on('update-not-available', () => { mainLogger.info('自動更新 沒有新版本') win.close() }) // 監(jiān)聽下載完成事件 autoUpdater.on('update-downloaded', () => { mainLogger.info('自動更新 新版本下載完成') // 重新啟動并安裝更新包 只有update-downloaded事件中可調(diào)用 autoUpdater.quitAndInstall() }) mainLogger.info('自動更新 開始檢查', AUTO_UPDATE_JSON_URL) // 設(shè)置安裝包所在服務(wù)器地址 autoUpdater.setFeedURL({ url: AUTO_UPDATE_JSON_URL, serverType: 'json' }) // 請求服務(wù)器是否有更新。 在使用此API之前,您必須調(diào)用setFeedURL autoUpdater.checkForUpdates() }
通過 autoUpdater Events 綁定相應(yīng)的事件,通過setFeedURL
方法設(shè)置安裝包的地址,最后通過checkForUpdates
檢查是否有更新,觸發(fā)綁定的各種事件。
當(dāng)檢測到有新版本時,顯示更新窗口,假進度條冒充下載中,自動下載安裝包
總結(jié)
本文主要講解如何解決 Error: Object has been destroyed
這個 Electron 中最常見的問題,以及 Electron 自動更新的流程。通過解決這個問題,意識到需要在 Electron 主進程中,要為代碼的關(guān)鍵點添加一些重要的日志信息,這樣在遇到問題時,能讓我們更加方便的定位問題。
以上就是Electron自動更新失效報錯Error: Object has been destroyed的問題解決的詳細內(nèi)容,更多關(guān)于Electron自動更新失效的資料請關(guān)注腳本之家其它相關(guān)文章!
- electron-vue+electron-updater實現(xiàn)自動更新(步驟源碼)
- Electron autoUpdater實現(xiàn)Windows安裝包自動更新的方法
- Windows下支持自動更新的Electron應(yīng)用腳手架的方法
- 如何使用electron-builder及electron-updater給項目配置自動更新
- electron-vue?運行報錯?Object.fromEntries?is?not?a?function的解決方案
- electron-vue中報錯Cannot?use?import?statement?outside?a?module的解決方案(親測有效!)
相關(guān)文章
Vue3中動態(tài)修改樣式與級聯(lián)樣式優(yōu)先順序圖文詳解
在項目中,我們時常會遇到動態(tài)的去綁定操作切換不同的CSS樣式,下面這篇文章主要給大家介紹了關(guān)于Vue3中動態(tài)修改樣式與級聯(lián)樣式優(yōu)先順序的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04如何用Vite構(gòu)建工具快速創(chuàng)建Vue項目
Vite是一個web開發(fā)構(gòu)建工具,由于其原生?ES?模塊導(dǎo)入方法,它允許快速提供代碼,下面這篇文章主要給大家介紹了關(guān)于如何用Vite構(gòu)建工具快速創(chuàng)建Vue項目的相關(guān)資料,需要的朋友可以參考下2022-05-05Vue實現(xiàn)預(yù)覽docx/xlsx/pdf等類型文件功能
這篇文章主要介紹了如何在Vue中實現(xiàn)docx/xlsx/pdf等類型文件預(yù)覽功能,在實現(xiàn)過程中,需要注意文件的格式和轉(zhuǎn)換方式,以及插件和組件的使用方法和注意事項,需要的朋友可以參考下2023-05-05