Electron自動(dòng)更新失效報(bào)錯(cuò)Error:?Object?has?been?destroyed的問題解決
Electron 自動(dòng)更新失敗
在 Electron 應(yīng)用某次更新,出現(xiàn)了如下循環(huán)更新的問題:
此時(shí),查詢?nèi)罩荆l(fā)現(xiàn)報(bào)錯(cuò)如下 Error: Object has been destroyed
:
問題原因
首先,通過查閱資料得知:在 Electron 中,當(dāng)一個(gè)窗口被銷毀后,與該窗口相關(guān)聯(lián)的 JavaScript 對(duì)象也會(huì)被銷毀,如果再次嘗試訪問已被銷毀的窗口對(duì)象時(shí),就會(huì)發(fā)出上圖所示的錯(cuò)誤。
通過日志可以很好的找到問題發(fā)生的地方(幸好我們主進(jìn)程中關(guān)鍵點(diǎn)都添加了明顯的日志信息,方便問題查找),很明顯是在 autoUpdater.on('update-available'
檢測(cè)到自動(dòng)更新后的報(bào)錯(cuò),那就著重排查下這里。
autoUpdater.on('update-available', () => { mainLogger.info('自動(dòng)更新 有新版本') 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()) { ... }
如何解決
為了避免這個(gè)錯(cuò)誤,需要在窗口對(duì)象被銷毀時(shí)取消訂閱所有與該窗口相關(guān)的事件,并在需要訪問窗口對(duì)象時(shí)先檢查窗口對(duì)象是否已經(jīng)被銷毀。
所以需要在調(diào)用窗口方法前,先判斷窗口是否已被銷毀
function onMainClose(e: Electron.Event) { if (isQuit) return if (!mainWindow?.isDestroyed()) return ...
重新打包,上傳成功后,再次出發(fā)自動(dòng)更新,即可正常了。順便說一下我們 Electron 應(yīng)用的更新流程。
打包
首先是打包,打包時(shí)需要更新 package.json 中的版本和說明
{ "version": "2.2.7", "versionNotes": "發(fā)現(xiàn)新版本 v2.2.7!\n\n1. 修復(fù)客服已知問題" }
修改完后,Mac 和 Windows 各自打包,并上傳到服務(wù)器。
自動(dòng)更新流程
關(guān)于 Electron 應(yīng)用的自動(dòng)更新,官方提供了更新應(yīng)用程序處理自動(dòng)更新過程。
因?yàn)槲覀兪褂玫?electron-builder 打包應(yīng)用,所以使用的是它內(nèi)置的更新程序Auto Update。
相比 Electron 中自帶的更新,它有以下優(yōu)勢(shì):
- 不需要搭建專用的發(fā)布服務(wù)器,可上傳到任意服務(wù)器;
- 代碼簽名驗(yàn)證可以在 macOS 和 Windows 上進(jìn)行;
- 支持下載進(jìn)度提示;
- 代碼簡單,工作量少。
實(shí)現(xiàn)過程
安裝依賴
yarn add electron-updater
主窗口調(diào)用
當(dāng)主窗口被激活顯示時(shí),通過 checkLatestVersion
方法檢查是否有版本更新
mainWindow.on('show', checkLatestVersion)
檢測(cè)是否有更新
checkLatestVersion
方法定義在主進(jìn)程的 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
方法用于檢測(cè)更新,主要通過比對(duì)服務(wù)器的安裝包版本是否大于本地版本,在本地打完包后,會(huì)將本地的包上傳到服務(wù)器上,同時(shí)會(huì)有一份 RELEASE.json
文件,就是通過比對(duì) RELEASE.json
文件中的 currentRelease
字段。
{ "currentRelease": "2.2.7", "notes": "發(fā)現(xiàn)新版本 v2.2.7!\n\n1. 修復(fù)客服已知問題。" }
當(dāng)大于本地版本即需要更新時(shí),顯示更新窗口(包含更新版本、更新說明等),當(dāng)用戶點(diǎn)擊更新
后,調(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)建了一個(gè)瀏覽器窗口,并加載 /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">正在更新中,更新完成后會(huì)自動(dòng)重啟,請(qǐng)耐心等待。</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>
頁面顯示一個(gè)假的進(jìn)度條即可,新版本下載完成后會(huì)自動(dòng)關(guān)閉并安裝。
autoUpdater 自動(dòng)更新
const checkMacUpdate = () => { const win = createAutoUpdateWindow() // 監(jiān)聽升級(jí)失敗事件 autoUpdater.on('error', (message) => { mainLogger.error('自動(dòng)更新', message) }) // 監(jiān)聽發(fā)現(xiàn)可用更新事件 autoUpdater.on('update-available', () => { mainLogger.info('自動(dòng)更新 有新版本') isUpdating = true disableStopMainWindowClose() win.show() mainWindow.destroy() }) // 監(jiān)聽沒有可用更新事件 autoUpdater.on('update-not-available', () => { mainLogger.info('自動(dòng)更新 沒有新版本') win.close() }) // 監(jiān)聽下載完成事件 autoUpdater.on('update-downloaded', () => { mainLogger.info('自動(dòng)更新 新版本下載完成') // 重新啟動(dòng)并安裝更新包 只有update-downloaded事件中可調(diào)用 autoUpdater.quitAndInstall() }) mainLogger.info('自動(dòng)更新 開始檢查', AUTO_UPDATE_JSON_URL) // 設(shè)置安裝包所在服務(wù)器地址 autoUpdater.setFeedURL({ url: AUTO_UPDATE_JSON_URL, serverType: 'json' }) // 請(qǐng)求服務(wù)器是否有更新。 在使用此API之前,您必須調(diào)用setFeedURL autoUpdater.checkForUpdates() }
通過 autoUpdater Events 綁定相應(yīng)的事件,通過setFeedURL
方法設(shè)置安裝包的地址,最后通過checkForUpdates
檢查是否有更新,觸發(fā)綁定的各種事件。
當(dāng)檢測(cè)到有新版本時(shí),顯示更新窗口,假進(jìn)度條冒充下載中,自動(dòng)下載安裝包
總結(jié)
本文主要講解如何解決 Error: Object has been destroyed
這個(gè) Electron 中最常見的問題,以及 Electron 自動(dòng)更新的流程。通過解決這個(gè)問題,意識(shí)到需要在 Electron 主進(jìn)程中,要為代碼的關(guān)鍵點(diǎn)添加一些重要的日志信息,這樣在遇到問題時(shí),能讓我們更加方便的定位問題。
以上就是Electron自動(dòng)更新失效報(bào)錯(cuò)Error: Object has been destroyed的問題解決的詳細(xì)內(nèi)容,更多關(guān)于Electron自動(dòng)更新失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- electron-vue+electron-updater實(shí)現(xiàn)自動(dòng)更新(步驟源碼)
- Electron autoUpdater實(shí)現(xiàn)Windows安裝包自動(dòng)更新的方法
- Windows下支持自動(dòng)更新的Electron應(yīng)用腳手架的方法
- 如何使用electron-builder及electron-updater給項(xiàng)目配置自動(dòng)更新
- electron-vue?運(yùn)行報(bào)錯(cuò)?Object.fromEntries?is?not?a?function的解決方案
- electron-vue中報(bào)錯(cuò)Cannot?use?import?statement?outside?a?module的解決方案(親測(cè)有效!)
相關(guān)文章
vue-router路由懶加載及實(shí)現(xiàn)的3種方式
這篇文章主要給大家介紹了關(guān)于vue-router路由懶加載及實(shí)現(xiàn)的3種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02element中drawer模板的實(shí)現(xiàn)
本文主要介紹了element中drawer模板的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Vue3中動(dòng)態(tài)修改樣式與級(jí)聯(lián)樣式優(yōu)先順序圖文詳解
在項(xiàng)目中,我們時(shí)常會(huì)遇到動(dòng)態(tài)的去綁定操作切換不同的CSS樣式,下面這篇文章主要給大家介紹了關(guān)于Vue3中動(dòng)態(tài)修改樣式與級(jí)聯(lián)樣式優(yōu)先順序的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04如何用Vite構(gòu)建工具快速創(chuàng)建Vue項(xiàng)目
Vite是一個(gè)web開發(fā)構(gòu)建工具,由于其原生?ES?模塊導(dǎo)入方法,它允許快速提供代碼,下面這篇文章主要給大家介紹了關(guān)于如何用Vite構(gòu)建工具快速創(chuàng)建Vue項(xiàng)目的相關(guān)資料,需要的朋友可以參考下2022-05-05Vue實(shí)現(xiàn)預(yù)覽docx/xlsx/pdf等類型文件功能
這篇文章主要介紹了如何在Vue中實(shí)現(xiàn)docx/xlsx/pdf等類型文件預(yù)覽功能,在實(shí)現(xiàn)過程中,需要注意文件的格式和轉(zhuǎn)換方式,以及插件和組件的使用方法和注意事項(xiàng),需要的朋友可以參考下2023-05-05