如何使用javascript异步下载文件?

can*_*an. 1 javascript asynchronous google-chrome-extension

我正在构建一个Chrome扩展程序,以从网站下载一系列文件。下载功能源自如何使用JavaScript从URL保存文件

程序结构如下:

function download()
{
  while(there're still files to download)
  {
    saveFile(url);
  }
}
Run Code Online (Sandbox Code Playgroud)

但是我发现所有文件实际上在download()返回后立即写入磁盘。这些文件的地址以blob:从Chrome的下载管理器中进行检查时开始。

我想知道是否可以saveFile异步调用这些文件,一次只能写入一个文件。

Esa*_*ija 5

使用Promise(可在Chrome中直接使用),您可以定义如下功能:

// Download a file form a url.
function saveFile(url) {
  return new Promise(function(resolve, reject) {
    // Get file name from url.
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';
    xhr.onload = function() {
      resolve(xhr);
    };
    xhr.onerror = reject;
    xhr.open('GET', url);
    xhr.send();
  }).then(function(xhr) {
    var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
    a.download = filename; // Set the file name.
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    return xhr;
  });
}

function download(urls) {
  return Promise.all(urls.map(saveFile));
}
Run Code Online (Sandbox Code Playgroud)

使用它:

download.then(function() {
  alert("all files downloaded");
}).catch(function(e) {
  alert("something went wrong: " + e);
});
Run Code Online (Sandbox Code Playgroud)

如果要等待1个文件下载然后再进行下一步,则下载功能应如下编写:

function download(urls) {
  var cur = Promise.resolve();
  urls.forEach(function(url) {
    cur = cur.then(function() {
      return saveFile(url);
    });
  });
  return cur;
}
Run Code Online (Sandbox Code Playgroud)

用法与以前相同。

  • 很好的答案。只是想知道您会在 2020 年使用相同的方法,或者您会应用任何 ES6+ 更新吗? (3认同)