優化electron客戶端卡頓的幾種方案


背景

公司需要做一個同步盤的客戶端,框架技術選型方面使用了支持跨平台的Electron框架,其中一些核心功能就是文件的上傳,和下載,考慮到node操作文件比較方便,起初把文件的下載上傳操作放到主進程,在大量文件下載和上傳時,造成了界面的卡頓,現在就這個問題進行剖析和優化。

 

解決卡頓

方案一

首先要確定是什么因素導致的卡頓,在平時,沒有上傳下載文件時,electron客戶端沒有出現卡頓的情況,然后對下載的流程進行跟蹤,通過打印log日記發現,在執行一個方法后后面的log無法輸出,然后界面失去了響應,其代碼如下

const  parentExist = (rpath: string) => {
const  root = store.get("syncPath") as  string;
let  parent = path.parse(rpath).dir.replaceAll("\\", "/");
let  localFilePath = path.join(root, parent);
let  isFalse = parent !== "/";
const  dirs = [];
try {
while (!fs.existsSync(localFilePath) && isFalse) {
dirs.push(localFilePath);
parent = path.parse(rpath).dir.replaceAll("\\", "/");
localFilePath = path.join(root, parent);
isFalse = parent !== "/";
}
for (const  dir  of  dirs) {
fs.mkdirSync(dir);
}
} catch (error) {
console.log(error);
}
};

 

好家伙,在while 循環里我做了parent = path.parse(rpath).dir.replaceAll(“\“, “/“);,應該是parent = path.parse(parent).dir.replaceAll(“\“, “/“); 不然parent 一直不等於”/“,這樣就一直循環出不來了,導致主進程卡頓失去響應。
解決這個問題后發現,卡頓依然存在,還需要繼續優化。

 

方案二

一般來說,造成卡頓的主要原因是主進程被阻塞了,雖然我使用的異步,但是,像之前的while 循環無線遞歸,雖然放在主進程,但是也會阻塞主進程,而下載上傳這樣的同步邏輯涉及到很多計算和資源的等待,於是,我對同步邏輯進行了整改,我把同步邏輯放在一個隱藏的渲染進程進行運行,通過ipc再進行交互.

進行了這一輪改造后,發現優化后的效果不太明顯。

 

方案三

經過前幾輪的優化,讓我對我渲染進程的邏輯有些思考,會不會是我的渲染進程的js代碼有問題,於是我重新審視了我的代碼,發現在獲取狀態圖標的時候,每個文件都需要調用ipc,通過主進程獲取文件的狀態,並且,每一個觸發同步操作時,都會通知渲染進程進行重新渲染,如果觸發頻率過高,就會一直觸發渲染,而且發現獲取狀態的回調時長有點長,平均每個1s,

const resust = await ipcRenderer.invoke("getFileStatus",
   this.getRLPath(filedir)
);

 

就是這段代碼。

於是我就將獲取狀態的方案重新整改。通過緩存的方式獲取,放到主進程的全局變量里,兩個渲染進程共同操作這個全局變量

 const statusCache: any = new mapCache();
  const statusCacheinit = async () => {
  const meta = new MetaData();
  const dbFile = await meta.getAll("");
  statusCache.clear();
  if (dbFile) {
    for (const file of dbFile) {
      if (statusCache.containKey(file.path)) {
        continue;
      } else {
        statusCache.add(file.path,  {
          path: file.path,
          status: "success",
          fileID: file.fileid,
          sharePerm: file.remotePerm.includes("R"),
          perm: file.remotePerm,
          collect: false,
          isShared: false
        });
      }
    }
  }
};
   global.statusCache = statusCache;

 
並且使用防抖,把刷新的頻率降低下來,

 debounce(
      () => {
        ipcRenderer.sendTo(this.mainID, "dirChange", filePath, evt);
      },
      2000,
      { maxWait: 5000 }
    )();

 

經過這次的方案整改后,整體的感覺沒有卡頓,用的比較流暢,當然后續還有優化空間

 

總結

用electron進行pc客戶端的開發坑還是有點多的,特別是優化這一塊,electron的優勢是js和html,他的缺點也是js和html,本來是想用多線程做這次的優化的,發現js 的Web Worker太難用了,而且不能使用electron模塊,這樣在web Worker處理的邏輯就不能方便的通知到渲染進程,所以對於卡頓優化這一塊,還是得通過其他方式進行優化,最最重要的是防止主進程阻塞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM