【问题标题】:How to return base64 data from a fetch promise?如何从获取承诺中返回 base64 数据?
【发布时间】:2019-08-04 13:17:02
【问题描述】:

我想将图像从 URL 转换为 base 64,并将其存储在一个状态以供以后使用。

如何从 fetch() 返回数据?

我可以使用 CORS 安全图像和 HTML 画布使其工作,但这不适用于公共域。

  openImage = (index) => {
    const url = formatURLs[index];
    const base64 = this.getBase64Image(url);

    this.setState(prevState => ({
      currentImage: index,
      currentImagebase64: base64
    }));
  }

  getBase64Image(url) {
    fetch(url).then(r => r.blob()).then(blob => {
      var reader = new FileReader();
      reader.onload = function() {
           var b64 = reader.result.replace(/^data:.+;base64,/, '');
           return b64;
      };
      reader.readAsDataURL(blob);
    });
  }

当我 console.log(reader.result) 时,它会按预期输出 base64。

但是,当我返回 b64 时,它会以“未定义”的形式返回到 openImage。

【问题讨论】:

  • 为什么不只存储 Blob?
  • fetch()asynchronous 所以你不能从像你这样的函数返回值。您可以在 .then() 回调中返回 Promise 并更新状态。
  • 您需要make a promise for the b64 data in the load event handler。然后你可以return 那些getBase64Image 返回一个承诺。更改 openImage 以等待 promise 的结果。
  • 不要制作它的 base64 版本。正如@Bergi 所说,您最好存储Blob。如果需要持久化,则使用 IndexedDb 来存储 Blob。当您需要显示图像时,请使用 blobURI (URL.createObjectURL)。如果您正在生成一个需要嵌入该文件的独立文档,您只需要一个 dataURI,而且您似乎不在这种非常罕见的情况下。

标签: javascript reactjs


【解决方案1】:

getBase64Image 是异步的,所以当以同步方式调用它时,它会返回 undefined。

你可以试试这样的

  openImage = async (index) => {
    const url = formatURLs[index];
    const base64 = await this.getBase64Image(url);
    this.setState(prevState => ({
      currentImage: index,
      currentImagebase64: base64
    }));
  }

  async getBase64Image(url) => {
    const response = await fetch(url);
    const blob = await response.blob();
    const reader = new FileReader();
    await new Promise((resolve, reject) => {
      reader.onload = resolve;
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
    return reader.result.replace(/^data:.+;base64,/, '')
  }

【讨论】:

  • 避免使用Promise constructor antipattern!编写一个单独的函数,该函数使用FileReader 并从blob 返回base64 字符串的promise。另外,如果你想使用async/await,你可能也应该在getBase64Image 中使用
  • @Bergi 谢谢,第二条评论你是对的,我很懒惰。对于第一个评论,你能详细说明你会怎么做吗?
  • 我希望你不介意编辑 - 一个更干净的解决方案是创建一个单独的函数来创建 new Promise :-) 修复它@PatrickRoberts
【解决方案2】:

你必须在 .then() 中设置状态

getBase64Image(url) {
    fetch(url).then(r => r.blob()).then(blob => {
      var reader = new FileReader();
      reader.onload = function() {
           var b64 = reader.result.replace(/^data:.+;base64,/, '');
           this.setState({
             currentImagebase64: b64
           });
      };
      reader.readAsDataURL(blob);
    });
  }

【讨论】:

  • 你应该从getBase64Image返回一个promise,并将setState保留在openImage函数中。
猜你喜欢
  • 2018-05-16
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
相关资源
最近更新 更多