var downloader = new Downloader(dataArray[i], options); downloader.data.timeid=timenow;//存储唯一标识 downloader.start(); downloader.onStart = () => { // 下载开始 handleDownload.push(downloader); mainWindow.webContents.send('consolelog2', '检查代码在此执行次数'); }; 这段代码中,为什么 new Downloader(dataArray[i], options); 执行第一次的时候 downloader.onStart = () => { // 下载开始 handleDownload.push(downloader); mainWindow.webContents.send('consolelog2', '检查代码在此执行次数'); }; 执行一次。 而 new Downloader(dataArray[i], options); 执行第二次的时候。 downloader.onStart = () => { // 下载开始 handleDownload.push(downloader); mainWindow.webContents.send('consolelog2', '检查代码在此执行次数'); }; 执行了两次
时间: 2024-04-28 19:27:06 浏览: 168
根据你提供的代码,我可以看出这是一个下载器的实现,当执行 new Downloader(dataArray[i], options); 时,会创建一个新的 Downloader 对象,并将其存储在变量 downloader 中。然后,通过设置 downloader.onStart 回调函数,将其推入 handleDownload 数组中,并向 mainWindow 发送一条消息。因此,当第一次执行 new Downloader(dataArray[i], options); 时,回调函数只会执行一次。但是,当第二次执行 new Downloader(dataArray[i], options); 时,会创建另一个新的 Downloader 对象,并将其存储在变量 downloader 中。然后,将其设置为回调函数并推入 handleDownload 数组中,再向 mainWindow 发送一条消息。因此,回调函数会执行两次。
相关问题
// 下载器类 class Downloader { constructor(data, options) { this.data = data; this.options = options; this.item = null; this.onStart = null; this.onProgress = null; this.onCompleted = null; this.data.progress = 0; // 新增 progress 属性 this.data.status='pause';//true 表示 进度没有结束,继续下载 this.data.timeid=0; } start() { const win = BrowserWindow.getFocusedWindow(); this.options.onStarted = (item) => { this.item = item; this.data.status='process';//true 表示 进度没有结束,继续下载 this.onStart(); if (!handleDownload.includes(item)) { handleDownload.push(item); } }; this.options.onTotalProgress=(progress)=>{ this.data.progress = progress.percent * 100; // 更新 progress 属性 this.onTotalProgress(progress); } this.options.onCompleted = () => { this.onCompleted(); }; download(win, this.data.dowloadLink, this.options); } pause() { if (this.item) { this.item.pause(); } } resume() { if (this.item) { this.item.resume(); } } cancel() { if (this.item) { this.item.cancel(); } } } ipcMain.handle('window-downloadNow', (msg, dataArray) => { for (var i=0;i<dataArray.length;i++) { var timenow=Date.now();//调用的时候,打个时间戳 const options = { directory: downloadPath, filename: dataArray[i].title + '.' + dataArray[i].fileType, saveAs: false, extension: dataArray[i].fileType, openFolderWhenDone: false, showProgressBar: true, showBadge: true, }; var downloader = new Downloader(dataArray[i], options); downloader.data.timeid=timenow;//存储唯一标识 downloader.start(); downloader.onStart = () => { // 下载开始 }; downloader.onTotalProgress = (progress) => { // 更新下载进度 downloadArray.set(downloader.data.timeid, { title: downloader.data.title, sUrl: downloader.data.sUrl, progress: downloader.data.progress, size: downloader.data.size, status:downloader.data.status, timeid:downloader.data.timeid }); mainWindow.webContents.send('consolelog2', JSON.stringify(handleDownload)); mainWindow.webContents.send('consolelog', downloadArray); mainWindow.webContents.send('donwloadStatus', true); }; downloader.onCompleted = () => { if(downloader.data.progress==100&&downloader.data.status=='process'){ mainWindow.webContents.send('endDownload', JSON.stringify(downloader)); mainWindow.webContents.send('donwloadStatus', false); downloader.data.status='complete' } if(downloader.data.progress<100){ mainWindow.webContents.send('donwloadStatus', true); } mainWindow.webContents.send('consolelog', downloadArray); }; } return JSON.stringify(dataArray); // 返回值将作为 Promise 的 resolved 值 }); 这个下载器有个问题,当dataArray 为24个时,下载的数据不是这24个,而是最后一个,为什么
这个问题可能是由于 JavaScript 中的闭包概念导致的。在 for 循环中,每次循环都会创建一个新的 downloader 对象并启动下载任务,但是在下载任务完成之前,循环就已经执行完毕了。此时,变量 i 的值已经变成了 24,而所有的 downloader 对象都共享了这个变量 i。当下载任务完成时,回调函数中的 i 值已经变成了 24,因此 downloadArray 中所有的元素都被更新为最后一个下载任务的信息。
要解决这个问题,可以使用 let 关键字代替 var,在每次循环中创建一个新的变量来存储当前循环的索引值。这样就可以避免闭包导致的问题。例如:
```javascript
for (let i = 0; i < dataArray.length; i++) {
// ...
}
```
另外,还可以将下载任务的启动和回调函数的绑定放在一个单独的函数中,避免在循环中重复创建对象。例如:
```javascript
function startDownload(dataArray, index) {
const options = { /* ... */ };
const downloader = new Downloader(dataArray[index], options);
downloader.data.timeid = Date.now();
downloader.onStart = () => { /* ... */ };
downloader.onTotalProgress = (progress) => { /* ... */ };
downloader.onCompleted = () => { /* ... */ };
downloader.start();
}
for (let i = 0; i < dataArray.length; i++) {
startDownload(dataArray, i);
}
```
这样就可以避免闭包导致的问题,同时也可以提高代码的可读性和可维护性。
class Downloader { constructor(data, options) { this.data = data; this.options = options; this.item = null; this.onStart = null; this.onProgress = null; this.onCompleted = null; this.data.progress = 0; // 新增 progress 属性 this.data.status='pause';//true 表示 进度没有结束,继续下载 this.data.timeid=0; } start() { const win = BrowserWindow.getFocusedWindow(); this.options.onStarted = (item) => { this.item = item; this.data.status='process';//true 表示 进度没有结束,继续下载 this.onStart(); handleDownload.push(item); }; this.options.onTotalProgress=(progress)=>{ this.data.progress = progress.percent * 100; // 更新 progress 属性 if(this.data.status=='process'){ this.onTotalProgress(progress); } } this.options.onCompleted = () => { this.onCompleted(); }; download(win, this.data.dowloadLink, this.options); } pause() { if (this.item) { this.item.pause(); } } resume() { if (this.item) { this.item.resume(); } } cancel() { if (this.item) { this.item.cancel(); } } } ipcMain.handle('window-downloadNow', (msg, dataArray) => { for (const data of dataArray) { var timenow=Date.now();//调用的时候,打个时间戳 const options = { directory: downloadPath, filename: data.title + '.' + data.fileType, saveAs: false, extension: data.fileType, openFolderWhenDone: false, showProgressBar: true, showBadge: true, }; const downloader = new Downloader(data, options); downloader.data.timeid=timenow;//存储唯一标识 downloader.start(); downloader.onStart = () => { // 下载开始 }; downloader.onTotalProgress = (progress) => { // 更新下载进度 downloadArray.set(downloader.data.timeid, { title: downloader.data.title, sUrl: downloader.data.sUrl, progress: downloader.data.progress, size: downloader.data.size, status:downloader.data.status, timeid:downloader.data.timeid }); mainWindow.webContents.send('consolelog', downloadArray); mainWindow.webContents.send('donwloadStatus', true); }; downloader.onCompleted = () => { if(downloader.data.progress==100&&downloader.data.status=='process'){ mainWindow.webContents.send('endDownload', JSON.stringify(downloader)); mainWindow.webContents.send('donwloadStatus', false); downloader.data.status='complete' } if(downloader.data.progress<100){ mainWindow.webContents.send('donwloadStatus', true); } mainWindow.webContents.send('consolelog', downloadArray); }; } return JSON.stringify(dataArray); // 返回值将作为 Promise 的 resolved 值 }); 这段代码中,handleDownload.push(item); 会重复push ,比如,点击下载歌曲A,此时handleDownload.push(item); 里面有A。 此时我下载歌曲B,此时 handleDownload.push(item); 重复push 了两次B,怎么回事?
这段代码中的 handleDownload 是一个数组,用于存储下载任务的 Item 对象。每次点击下载按钮,都会创建一个新的 Downloader 对象,并调用 start 方法开始下载,同时将对应的 Item 对象存储在 handleDownload 数组中。
当你下载歌曲 A 时,handleDownload 数组中存储了 A 对应的 Item 对象;当你下载歌曲 B 时,handleDownload 数组中已经存储了 A 对应的 Item 对象,因此会出现重复 push B 的情况。
解决方法是在下载完成后将对应的 Item 对象从 handleDownload 数组中移除,可以在 Downloader 对象的 onCompleted 事件中实现,例如:
```
downloader.onCompleted = () => {
const index = handleDownload.indexOf(downloader.item);
if (index >= 0) {
handleDownload.splice(index, 1);
}
// ...
};
```
阅读全文