切换导航栏路由后使用electron-dl启动下载出现循环问题求助
问题解决:路由切换后下载流程循环问题
问题描述
切换导航栏路由后启动下载流程时出现循环问题,相关代码如下:
function downloaddosya1() { console.log("Files1 downloading...") const url = "http://ipv4.download.thinkbroadband.com/100MB.zip" ipcRenderer.invoke("downloadmng",url); } // DOSYA 1 function checkdosya() { const yereldosya = 'C:\\test\\xampp-control.exe' const yereldosyahash ='ed4d6fdb6248bcff64e5652cd0c9d79c483bace94c1120dc3128645f00a5e5c4' fs.exists(yereldosya, function(exists) { if (exists) { console.log("Dosya Var") getChecksum(yereldosya) .then(checksum => { apidosya(checksum) }) .catch(err => console.log(err)); const apidosya = async(checksum) => { if(checksum == yereldosyahash){ checkdosyadone() }else{ console.log("Files 1 False") downloaddosya1() } } }else{ console.log("Dosya Yok") downloaddosya1() } }); }
问题分析
- 未等待下载完成就重复校验:
downloaddosya1调用IPC发起下载后,没有等待下载完成就可能再次触发checkdosya,导致反复校验、反复下载,形成循环。 - 路由切换引发重复触发:路由切换后页面组件可能重新挂载,
checkdosya被重复调用,旧的下载流程未终止,新旧流程叠加导致循环。 - 函数定义时序错误:
apidosa定义在fs.exists的回调内部,每次调用checkdosya都会重新定义该函数,且getChecksum的then回调调用时,函数可能还未完成定义,存在时序混乱问题。
解决方案
1. 修正函数定义与异步等待逻辑
将apidosa移到checkdosya外部,同时让下载函数返回Promise,确保下载完成后再执行校验:
// 提前定义校验逻辑函数 async function apidosya(checksum, targetHash) { if(checksum === targetHash){ checkdosyadone() } else { console.log("Files 1 False") // 等待下载完成后再重新校验 await downloaddosya1() checkdosya() } } // 修改下载函数为异步,等待IPC下载完成 async function downloaddosya1() { console.log("Files1 downloading...") const url = "http://ipv4.download.thinkbroadband.com/100MB.zip" await ipcRenderer.invoke("downloadmng", url); } function checkdosya() { const yereldosya = 'C:\\test\\xampp-control.exe' const yereldosyahash ='ed4d6fdb6248bcff64e5652cd0c9d79c483bace94c1120dc3128645f00a5e5c4' fs.exists(yereldosya, function(exists) { if (exists) { console.log("Dosya Var") getChecksum(yereldosya) .then(checksum => apidosya(checksum, yereldosyahash)) .catch(err => { console.log(err) // 校验失败直接触发下载,完成后重新校验 downloaddosya1().then(() => checkdosya()) }); } else { console.log("Dosya Yok") downloaddosya1().then(() => checkdosya()) } }); }
2. 路由切换时清理旧任务
在路由切换前,取消正在进行的下载任务(需要主进程的downloadmng实现支持取消功能),避免新旧任务冲突:
let currentDownloadTask = null; async function downloaddosya1() { // 存在未完成任务则先取消 if(currentDownloadTask) { await ipcRenderer.invoke("cancel-download", currentDownloadTask.id); currentDownloadTask = null; } console.log("Files1 downloading...") const url = "http://ipv4.download.thinkbroadband.com/100MB.zip" currentDownloadTask = await ipcRenderer.invoke("downloadmng", url); } // 路由切换钩子中加入清理逻辑 router.beforeEach((to, from, next) => { if(currentDownloadTask) { ipcRenderer.invoke("cancel-download", currentDownloadTask.id); currentDownloadTask = null; } next(); });
3. 防止checkdosya重复触发
添加标志位,确保同一时间只有一个校验流程在执行:
let isChecking = false; function checkdosya() { if(isChecking) return; isChecking = true; const yereldosya = 'C:\\test\\xampp-control.exe' const yereldosyahash ='ed4d6fdb6248bcff64e5652cd0c9d79c483bace94c1120dc3128645f00a5e5c4' fs.exists(yereldosya, function(exists) { if (exists) { console.log("Dosya Var") getChecksum(yereldosya) .then(checksum => apidosya(checksum, yereldosyahash)) .catch(err => { console.log(err) downloaddosya1().then(() => { isChecking = false; checkdosya() }) }); } else { console.log("Dosya Yok") downloaddosya1().then(() => { isChecking = false; checkdosya() }) } }); } async function apidosya(checksum, targetHash) { if(checksum === targetHash){ checkdosyadone() isChecking = false; } else { console.log("Files 1 False") await downloaddosya1() isChecking = false; checkdosya() } }
关键注意点
- 必须等待下载完成后再执行校验,避免未完成下载就重复触发流程。
- 路由切换时务必清理未完成的任务,防止新旧任务冲突。
- 确保函数定义和调用的时序正确,避免因作用域或变量提升导致逻辑错误。
内容的提问来源于stack exchange,提问作者Sinan BENLİBAŞ
相关产品推荐
相关产品推荐

