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

Efr*_*aín 2 javascript google-chrome-extension

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

首先,我尝试搜索 Downloads 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'
        });

    }
Run Code Online (Sandbox Code Playgroud)

我在 while 上放置了一个计数器,因为我的其他测试的循环使我的浏览器崩溃,但如果有一种方法可以在开始下一个之前检查下载结束之前是否会更好。这是我用来进行更改的侦听器,只是为了清楚起见,我尝试将搜索方法放在上一个代码中,即使在 while 内,它也不起作用。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)
Run Code Online (Sandbox Code Playgroud)

wOx*_*xOm 6

回调:

将一个“步骤”提取到一个函数中,并从 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();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法: 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');
      }
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

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