javascript - 如何让 Chrome 下载 API 等到下载结束?

标签 javascript google-chrome-extension

我在尝试进行扩展时遇到问题。扩展的作用非常简单,我有一个带有一系列图像的 URL,我得到所有图像的 src,然后使用 chrome 的下载 API 将它们下载到一个文件夹中。我有它,而且效果很好,但是有一个问题,所有的下载都是连续开始的,这不断地导致一些下载失败,所以我试图让 Chrome 等到下载完成后再开始另一个。

首先我尝试搜索下载 API 是否有方法来验证这一点,但是,至少从我搜索的内容来看,我还没有找到获取 DownloadItem 的方法,只有两种方法可以做到这一点,使用搜索和自己的下载方法,但都使用似乎是异步的回调,然后我尝试在下载之前添加一段时间,并使用其中一种方法更改它的条件,但总是循环自身,因为它在while 循环不会继续它们的回调,与 handleChanged() 等全局方法相同。那么,我怎样才能让 Chrome 等到下载结束后再开始另一个下载而不循环呢?

这是我用于下载的部分代码

    for(let i=0; i<images.length; i++) {
        // Download image
        while(currentDownload) {
            if (cont == 10000000) {
                currentDownload = false;
            } else {
                cont = cont + 1;
            }
        };
        cont = 0;
        currentDownload = true;
        var downloadUrl = images[i].split(" . ")[0];
        img = images[i].split(" . ")[1];
        console.log(name+"/"+img);
        var downloading = chrome.downloads.download({
            url: downloadUrl,
            filename: name+"/"+img,
            conflictAction: 'uniquify'
        });

    }

我在 while 上设置了一个计数器,因为我的其他测试的循环导致我的浏览器崩溃,但如果有一种方法可以检查直到下载结束,然后再开始下一个测试,那就更好了。这是我用来进行更改的监听器,为了清楚起见,我尝试将搜索方法放在 prev 代​​码上,甚至在一段时间内,它只是没有用。 currentDownload 是一个全局变量。

function handleChanged(delta) {
    //if (urlRegexD.test(pest)) {

        if (delta.state && delta.state.current === "complete") {
            console.log(`Download ${delta.id} has completed.`);
            currentDownload = false;

        }
    //}
}

chrome.downloads.onChanged.addListener(handleChanged)

最佳答案

回调:

将一个“步骤”提取到一个函数中并从 onChanged 事件监听器中调用它。

function downloadSequentially(urls, callback) {
  let index = 0;
  let currentId;

  chrome.downloads.onChanged.addListener(onChanged);

  next();

  function next() {
    if (index >= urls.length) {
      chrome.downloads.onChanged.removeListener(onChanged);
      callback();
      return;
    }
    const url = urls[index];
    index++;
    if (url) {
      chrome.downloads.download({
        url,
      }, id => {
        currentId = id;
      });
    }
  }

  function onChanged({id, state}) {
    if (id === currentId && state && state.current !== 'in_progress') {
      next();
    }
  }
}

用法:downloadSequentially(arrayOfStringUrls, () => console.log('done'))


异步/等待:

将 API 调用封装在 Promise 中并等待它们。

async function downloadSequentially(urls) {
  for (const url of urls) {
    if (!url) continue;
    const currentId = await download(url);
    const success = await onDownloadComplete(currentId);
  }
}

function download(url) {
  return new Promise(resolve => chrome.downloads.download({url}, resolve));
}

function onDownloadComplete(itemId) {
  return new Promise(resolve => {
    chrome.downloads.onChanged.addListener(function onChanged({id, state}) {
      if (id === itemId && state && state.current !== 'in_progress') {
        chrome.downloads.onChanged.removeListener(onChanged);
        resolve(state.current === 'complete');
      }
    });
  });
}

用法:await downloadSequentially(arrayOfStringUrls) - 在 async 函数内。

关于javascript - 如何让 Chrome 下载 API 等到下载结束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51600832/

相关文章:

javascript - 防止 JS 弄乱我的媒体特定样式表

javascript - Chrome 扩展程序,如何将消息从面板发送到内容脚本

javascript - 登录后在 chrome 扩展中弹出窗口

javascript - 启动 Node 服务器,每天在特定时间加载页面

javascript - setTimeout 如何工作?

javascript - 包装页面 JavaScript 代码的正确方法

javascript - 请求特定外部协议(protocol)时可以打开 Chrome 扩展吗?

javascript - Chrome 扩展程序 - 在鼠标悬停在扩展程序图标上时显示动态文本

javascript - chrome.management.get 不工作

javascript 表单验证不适用于 chrome 和 FF