承诺Pouch不会从调用返回到内部代码

时间:2017-03-28 23:47:41

标签: javascript promise pouchdb

我承诺以前似乎有效,但现在没有。

我认为我已经完成了所有工作,但是在调用.get之后,它永远不会进入for循环。

它跳到最后并超出承诺,然后返回到返回(在.get内)然后到决心然后退出。

如果有错误,它应该跳转到catch但是没有,那么它是如何错过for循环的?

以下是代码:

    function readAllImagesFromPouch(id, imageDisplay) {

       return new Promise(function (resolve, reject) {

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

          // Get all attachments for this id

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

         for (var key in doc._attachments) {

            DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {
               var img = document.createElement('img');
               blob = resizeImage(blob, "100", "60");
               var url = URL.createObjectURL(blob);
               img.src = url;
               //alert(img.outerHTML);

               //startElement.appendChild(img);
               $(startElement).append("<div class='row' style='border:1px solid black'><div class='col-xs-10'>" +
                           img.outerHTML +
                           "</div>" +
                           "<div class='col-xs-1' style='padding-top:20px'>" +
                           "<img src='../Images/delete.png' alt='Delete'  class='taskimage'>" +
                           "</div></div>"
                        );
               return;
            }).catch(function () {
               console.log("No attachment for doc._id: " + doc._id + " and key: " + key);
            })
         }
         return;
          }).then(function () {
            resolve();
          }).catch(function (err) {
         console.log("Image not there for id: " + id);
         showMsg("Image not there for id: " + id);
         reject(err);
          })
       });         // end of promise
    }

从这段代码调用它:

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

谢谢,

汤姆

2 个答案:

答案 0 :(得分:0)

首先,避免使用promise构造函数反模式。当DB_TaskImages.get返回一个承诺时,您不需要创建一个

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

可能会重写您的代码:

function readAllImagesFromPouch(id, imageDisplay) {

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

    // Get all attachments for this id

    return DB_TaskImages.get(id, {
        attachments: true
    })
    .then(function(doc) {
        // a promise to chain to - all following tasks will be performed in series, not parallel - this can be changed
        var promise = Promise.resolve();
        Object.keys(doc._attachments).forEach(function(key) {
            promise = promise.then(function() {
                return DB_TaskImages.getAttachment(doc._id, key)
                .then(function(blob) {
                    var img = document.createElement('img');
                    blob = resizeImage(blob, "100", "60");
                    var url = URL.createObjectURL(blob);
                    img.src = url;
                    //alert(img.outerHTML);

                    //startElement.appendChild(img);
                    $(startElement).append("<div class='row' style='border:1px solid black'><div class='col-xs-10'>" +
                                           img.outerHTML +
                                           "</div>" +
                                           "<div class='col-xs-1' style='padding-top:20px'>" +
                                           "<img src='../Images/delete.png' alt='Delete'  class='taskimage'>" +
                                           "</div></div>"
                                          );
                    return;
                })
                .catch(function() {
                    console.log("No attachment for doc._id: " + doc._id + " and key: " + key);
                })
            });
        });
        return promise;
    })
    .catch(function(err) {
        console.log("Image not there for id: " + id);
        showMsg("Image not there for id: " + id);
        throw err;
    })
}

以上代码会串联调用DB_TaskImages.getAttachment(doc._id, key)

如果您可以并且想要并行执行DB_TaskImages.getAttachment(doc._id, key),则代码需要更多工作

function readAllImagesFromPouch(id, imageDisplay) {

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

    // Get all attachments for this id

    return DB_TaskImages.get(id, {
        attachments: true
    })
    .then(function(doc) {
        return Promise.all(Object.keys(doc._attachments)
            .map(function(key) {
                return DB_TaskImages.getAttachment(doc._id, key)
                // an error here should NOT reject the Promise.all, so handle the error and return undefined
                .catch(function() {
                    console.log("No attachment for doc._id: " + doc._id + " and key: " + key);
                })
            })
        );
    })
    .then(function(blobs) {
        return blobs.filter(function(blob) {
            // a failed .getAttachment results in an undefined result here, so ignore it
            return blob !== undefined;
        }).forEach(function(blob) {
            var img = document.createElement('img');
            blob = resizeImage(blob, "100", "60");
            var url = URL.createObjectURL(blob);
            img.src = url;
            $(startElement).append(
                "<div class='row' style='border:1px solid black'>" +
                    "<div class='col-xs-10'>" +
                        img.outerHTML +
                    "</div>" +
                    "<div class='col-xs-1' style='padding-top:20px'>" +
                        "<img src='../Images/delete.png' alt='Delete'  class='taskimage'>" +
                    "</div>" +
                "</div>"
            );
        });
    })
    .catch(function(err) {
        console.log("Image not there for id: " + id);
        showMsg("Image not there for id: " + id);
        throw err;
    })
}

答案 1 :(得分:0)

这可能不是正确的方法,但我想显示我更改的代码,看看这是否是正确的方法。这实际上是@jaromandaX回答的另一个问题的一部分。

这是同样的问题 - 如何处理承诺中的承诺。

查看你的代码resizeImage代码有一个问题,因为blob不是真正的blob,我想,这就是为什么我必须在我的另一个例子中使用blobutil。这真的是一个如何处理这个承诺的问题 - 如果我需要这样做的话。

我的旧代码是:

function resizeImageOld(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL
   var showImage = document.createElement('img');
   var url = URL.createObjectURL(blob);
   showImage.src = url;

   var newImage;

   showImage.onload = function () {
      URL.revokeObjectURL(showImage.src);
      var canvas = document.createElement("canvas");
      var ctx = canvas.getContext("2d");

      var MAX_WIDTH = maxWidth, maxHeight;
      var MAX_HEIGHT = 60;
      var width = showImage.width;
      var height = showImage.height;

      if (width > height) {
     if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
     }
      } else {
     if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
     }
      }

      canvas.width = width;
      canvas.height = height;

      ctx.drawImage(showImage, 0, 0, width, height);
      newImage = canvas.toDataURL("image/png");
   }
   return newImage;
}

将其作为承诺是一种在处理另一个图像之前将blob调整大小并附加到DOM的方法。这样它就不会发生onload事件。

我把它改为:

function resizeImage(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL

   return new Promise(function (resolve, reject) {

      var showImage = document.createElement('img');
      var url = URL.createObjectURL(blob);
      var newImage;

      showImage.onload = function () {
     URL.revokeObjectURL(showImage.src);
     var canvas = document.createElement("canvas");
     var ctx = canvas.getContext("2d");

     var MAX_WIDTH = maxWidth, maxHeight;
     var MAX_HEIGHT = 60;
     var width = showImage.width;
     var height = showImage.height;

     if (width > height) {
        if (width > MAX_WIDTH) {
           height *= MAX_WIDTH / width;
           width = MAX_WIDTH;
        }
     } else {
        if (height > MAX_HEIGHT) {
           width *= MAX_HEIGHT / height;
           height = MAX_HEIGHT;
        }
     }

     canvas.width = width;
     canvas.height = height;

     ctx.drawImage(showImage, 0, 0, width, height);
     newImage = canvas.toDataURL("image/png");

     resolve(newImage);
      }

      showImage.src = url;
   })
}

然后我改变了你的代码,现在将这个承诺调用到以下内容并想看看这是否是正确的处理方式,或者它是否会跳出承诺继续并在它经过后再回来其他图像。它似乎更好但不确定。

您的代码:

function readAllImagesFromPouch(id, imageDisplay) {

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

   ClearImagePanel();

   // Get all attachments for this id

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

      // a promise to chain to - all following tasks will be performed in series, not parallel - this can be changed

      var promise = Promise.resolve();

      Object.keys(doc._attachments).forEach(function (key) {
     promise = promise.then(function () {
        return DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {

           img = document.createElement('img');

           return resizeImage(blob, "100", "60").then(function(blob) {
          var url = URL.createObjectURL(blob);

          img.src = myUrl;
          $(startElement).append(img.outerHTML);

           })
        }).catch(function (err) {
           alert("No attachment for doc._id: " + doc._id + " and key: " + key);
        })
     });
      });
      return promise;
   }).catch(function (err) {
      console.log("Image not there for id: " + id);
      showMsg("Image not there for id: " + id);
      throw err;
   })
}

这是对的还是你之前提到过的那种反模式?

我还有另外两个我无法在其他地方找到的问题。

  1. 关于链的初始承诺(在这种情况下为DB_TaskImages.getAttachment),我们是否做了&#34;返回&#34;因为我们回到了以下&#34;然后&#34;?我不确定,因为我看过有回报的例子和其他没有回复第一个承诺的例子。

  2. 在我的例子中,对于&#34;返回resizeImage&#34;我承诺,在它之后我需要一个.then以及它吗?我注意到,在你做了#34;返回承诺&#34;之后,没有。然后有一个问题。

  3. 好奇。

    感谢。