【问题标题】:Resizing image using promise and pouch使用 promise 和 pouch 调整图像大小
【发布时间】:2017-08-23 13:39:23
【问题描述】:

我之前问过这个问题,并尝试根据一些答案对其进行更改,但仍然对 promise 有疑问。

这实际上是多个承诺,但主要问题是我正在调用 pouch.get 来获取图像列表。然后我通过一个 for/loop 创建一些标记(如果我没有调整大小的承诺代码,它可以正常工作)。我正在尝试创建一堆缩略图图像以网格形式显示在手机上。

我承诺调整大小的代码在去调整另一个图像大小之前尝试完成调整大小。但它最终只为最后一张图片执行了一个 onload 事件,仅此而已。

发生的情况是,对于每个循环,它都会进入调整大小,设置 onload 事件,将 url 复制到图像然后跳出并执行下一个循环,并且直到最后一个循环才会触发 onload 事件(图像),它显示在屏幕上。

我的调整大小承诺:

function resizeImageToImgPromise(showImage, maxWidth, maxHeight, url) {
   // Set img src to ObjectURL

   return new Promise(function (resolve, reject) {
      var test;
      test = 'test';
      showImage.onload = function () {
     URL.revokeObjectURL(this.src);
     var canvas = document.createElement("canvas");
     var ctx = canvas.getContext("2d");


   ... removed code to make it easier to read and not germane to the issue

     showImage.src = canvas.toDataURL("image/png");
     showImage.width = width;
     showImage.height;
     showImage.style.display = "inline";
     showImage.style.margin = "10px"

     resolve();
      }

      showImage.src = url;
   })
}

这是在 for 循环中调用它的 Promise:

function readAllImagesFromPouch(id, imageDisplay) {

   return new Promise(function (resolve, reject) {

      var startElement = document.getElementById(imageDisplay);
      var image = "";
      var imgBlob;
      var base64str;

      // Get all attachments for this id

      DB_TaskImages.get(id, { attachments: true }).then(function (doc) {

     for (var key in doc._attachments) {
        var img = document.createElement('img');
        base64str = doc._attachments[key].data;
        blobUtil.base64StringToBlob(base64str).then(function (myBlob) {
           console.log();
           return blobUtil.createObjectURL(myBlob);
        }).then(function (myUrl) {

           img.src = myUrl;

           resizeImageToImgPromise(img, "100", "60", myUrl).then(function () {

          $(startElement).append(img.outerHTML);                              return;
           }).catch(function () {    // this is the catch for the resize
          alert("this is an error");
           })
        }).catch(function (err) {   // this is the catch for the blobUtil
           // error
        });
     }
     return;
      }).then(function () {
     resolve();
      }).catch(function (err) {      // this is the catch for the DB_TaskImages.get
     reject(err);
      })
   });         // end of promise
}

这最初是从以下位置调用的:

    readAllImagesFromPouch("006", "divImages").then(function () {
    }).catch(function (err) {
       console.log("In catch for readAllImagesFromPouch with err: " + err);
    })

【问题讨论】:

  • 我认为我以前的回答根本没有帮助? stackoverflow.com/a/43081942/5053002 - 也许你可以告诉我那个代码有什么问题 - 我假设我的代码不起作用,因为你在这个问题中的代码仍然使用 Promise 构造函数反模式并盲目循环 doc._attachments 进行异步调用跨度>
  • 您的代码的主要问题是var img = document.createElement('img'); 在循环中被分配给每个doc._attachments - 异步代码直到结束才开始 for...in 循环 - 因此,所有异步代码的 img 是最后一个
  • 另外,this is the catch for the resize - 你的 resize 永远不会拒绝,因为唯一的错误来源将在 showImage.onload 回调中,这些不会变成“拒绝” - 当然,如果removed 代码中包含reject 调用,则可以忽略此注释
  • @JaromandaX:这有点令人困惑。我不确定反模式是什么。我现在知道,你所说的异步代码直到循环结束才开始是正确的。它实际上在 for 循环之后执行所有三行,然后执行 blobutil 的“then”相同数量的循环,然后执行调整大小部分,但直到最后才执行加载,然后由于某种原因会执行他们无限。如果我注释掉调整大小的承诺,它将按照我的意愿显示我的所有图像(除非它们不会被调整大小)。我真的不知道如何解决这个问题。
  • @JaromandaX:我没有在另一篇文章中看到我的代码被重写。我会看看它,看看它是否解决了我的问题。谢谢。

标签: javascript jquery image promise pouchdb


【解决方案1】:

首先,避免使用 Promise 构造函数反模式。由于DB_TaskImages.get 返回一个promise,你不需要将代码包装在一个中

其次,您的 for...in 循环启动了一堆异步任务 - 但您实际上并没有等待它们完成

此代码将遍历doc._attachments 并以“并行”方式执行resize - 只有在所有调整大小完成后才会显示调整大小的图像

function readAllImagesFromPouch(id, imageDisplay) {
    var startElement = document.getElementById(imageDisplay);
    return DB_TaskImages.get(id, {
        attachments: true
    }).then(function(doc) {
        return Promise.all(Object.keys(doc._attachments)
            .map(function(key) {
                var base64str = doc._attachments[key].data;
                return blobUtil.base64StringToBlob(base64str)
                .then(blobUtil.createObjectURL)
                .then(function(myUrl) {
                    return resizeImageToImgPromise("100", "60", myUrl);
                });
            })
        );
    }).then(function(images) {
        images.forEach(function(img) {
            $(startElement).append(img.outerHTML);
        });
    });
}

注意:没有进行错误处理,因此任何时候的任何错误都将导致不显示图像

【讨论】:

  • 我添加了 resize 函数来查看 promise 是否导致它失败。
  • 请不要使用您的代码编辑答案 - 如果您有答案,您可以发布答案,或者使用更新的代码编辑您的问题
  • 我刚刚弄清楚这里发生了什么。在 onload 部分中,它将更改的图像移动到 onload 所在的图像中。所以我猜它只是一直在运行。
  • 我只需要将 showImage.src 设为空即可使其正常工作。它现在可以正常工作。我只需要更仔细地看看你做了什么来理解它。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 2014-03-24
  • 2023-03-09
  • 1970-01-01
  • 2015-05-02
  • 2011-09-07
相关资源
最近更新 更多