From 9e84f84ae83e85d12170540a280bb6beb43ab471 Mon Sep 17 00:00:00 2001 From: k2s Date: Thu, 5 Oct 2023 12:15:52 +0200 Subject: [PATCH] Fix `await download()` when calling `item.cancel()` (#164) Co-authored-by: Sindre Sorhus --- index.d.ts | 12 ++++++++++++ index.js | 13 +++++++++---- readme.md | 12 ++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/index.d.ts b/index.d.ts index 66ffa8f..acfd279 100644 --- a/index.d.ts +++ b/index.d.ts @@ -130,8 +130,18 @@ declare namespace electronDl { } } +/** +Error thrown if `item.cancel()` was called. +*/ +declare class CancelError extends Error {} + // eslint-disable-next-line no-redeclare declare const electronDl: { + /** + Error thrown if `item.cancel()` was called. + */ + CancelError: typeof CancelError; + /** Register the helper for all windows. @@ -157,6 +167,8 @@ declare const electronDl: { @param window - Window to register the behavior on. @param url - URL to download. @returns A promise for the downloaded file. + @throws {CancelError} An error if the user calls `item.cancel()`. + @throws {Error} An error if the download fails. @example ``` diff --git a/index.js b/index.js index cb0879f..05dbff2 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,8 @@ const unusedFilename = require('unused-filename'); const pupa = require('pupa'); const extName = require('ext-name'); +class CancelError extends Error {} + const getFilenameFromMime = (name, mime) => { const extensions = extName.mime(mime); @@ -92,10 +94,6 @@ function registerListener(session, options, callback = () => {}) { item.setSavePath(filePath); } - if (typeof options.onStarted === 'function') { - options.onStarted(item); - } - item.on('updated', () => { receivedBytes = completedBytes; for (const item of downloadItems) { @@ -154,6 +152,7 @@ function registerListener(session, options, callback = () => {}) { if (typeof options.onCancel === 'function') { options.onCancel(item); } + callback(new CancelError()); } else if (state === 'interrupted') { const message = pupa(errorMessage, {filename: path.basename(filePath)}); callback(new Error(message)); @@ -182,6 +181,10 @@ function registerListener(session, options, callback = () => {}) { callback(null, item); } }); + + if (typeof options.onStarted === 'function') { + options.onStarted(item); + } }; session.on('will-download', listener); @@ -214,3 +217,5 @@ module.exports.download = (window_, url, options) => new Promise((resolve, rejec window_.webContents.downloadURL(url); }); + +module.exports.CancelError = CancelError; diff --git a/readme.md b/readme.md index 5a49a78..cdb96ee 100644 --- a/readme.md +++ b/readme.md @@ -50,7 +50,15 @@ const {download} = require('electron-dl'); ipcMain.on('download-button', async (event, {url}) => { const win = BrowserWindow.getFocusedWindow(); - console.log(await download(win, url)); + try { + console.log(await download(win, url)); + } catch (error) { + if (error instanceof electronDl.CancelError) { + console.info('item.cancel() was called'); + } else { + console.error(error); + } + } }); ``` @@ -128,7 +136,7 @@ Note: Error dialog will not be shown in `electronDl.download()`. Please handle e Type: `Function` Optional callback that receives the [download item](https://electronjs.org/docs/api/download-item). -You can use this for advanced handling such as canceling the item like `item.cancel()`. +You can use this for advanced handling such as canceling the item like `item.cancel()` which will throw `electronDl.CancelError` from the `electronDl.download()` method. #### onProgress