承诺从数组

时间:2017-04-10 09:45:01

标签: javascript promise

我有一个数组,它有一个图像ID,名称和图像本身(base64)。在某些情况下,id会匹配,因此需要使用不同的过程和参数的修订号。但它们必须按顺序运行,以便知道id是否已经存在。

我承诺完成所有这些并且每次都需要调用,但我似乎无法找到最佳方法。网上的一些想法正在使用" reduce"但不确定这是如何运作的。

代码是:

    function resetImagesToPouch(image, id, imageName) {

       return new Promise(function (resolve, reject) {

          var rev;
          var imageType;

          // check if attachment already exists

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

         rev = doc._rev;    // Get the revision number since we are updating and adding attachment to existing doc.

         DB_TaskImages.putAttachment(id, imageName, rev, image, "image/jpeg").then(function () {
            console.log("Attachment added successfully");
            return;
         }).then(function () {
            resolve();
         }).catch(function (err) {
            reject(err);
         });
         return;
          }).catch(function (err) {
         if (err.status = '404') {      // if this is a new document - add new attachment
            //imageType = GetImageTypeFromBase64(image);
            DB_TaskImages.putAttachment(id, imageName, image, "image/jpeg").then(function () {
               console.log("Attachment added successfully");
               return;
            }).then(function () {
               resolve();
            }).catch(function (err) {
               reject(err);
            })
         }
          });
       });      // end promise
    }

我需要刷新表格所需的图像数组,例如:

    images = {
            {id = "111", imageName='fighter.jpg', image='aaaaaddddd'},
            {id = "111", imageName='horse.jpg', image='aaasdfssdaaddddd'},
            {id = "112", imageName='cat.jpg', image='aasdfaaadsdfsfdddd'},
            {id = "113", imageName='dog.jpg', image='aaasdfasfaaaddddd'},
            {id = "1234", imageName='apple.jpg', image='aaaasdfasaaddddd'}
         }

我不知道数组中有多少或数值是多少。我该怎么做?我不能使用Promise.all(我不这么认为),因为他们不能一起开火,但.get和.put是异步的,我需要每个承诺完成。我不能使用那些因为我不知道会有多少人。

由于

下面的答案很好,除了它是链的一部分并在完成之前退出代码。

   }).then(function () {
      return ajaxCallForJsonTwoResults(URI_WorkIssues);
   }).then(function (args) {
      args[1].reduce(function (promise, image) {
     return promise.then(function () {
        return resetImagesToPouch(image);
     });
      }, Promise.resolve(args)).then(function () {
     console.log('all done with images');
      });
   }).then(function (args) {
      return callBulkDocLoad(DB_WorkIssues, args[0]);
   }).then(function () {

在代码中,我传递了args(其中有两个数组 - args [0]和args [1])。我在这里处理两个数据库所以我需要两个回复。问题是当我从我的ajax调用回来时,我使用args [1]作为第一个promise,而args [0]作为另一个。但是,由于我过早地从第一个承诺中回来,并且尚未达到将args传递给callBulkDocLoad函数的决心,因此未定义。

我错过了什么吗?

感谢。

它几乎可以工作。

返回确实使循环在跳出之前完成了reduce循环但是它没有执行resetImagesToPouch调用,直到完成所有循环并且只执行一次。

      var argsSaved;
          ...
          // WorkIssues
   }).then(function () {
      if (DB_WorkIssues != null)
     return DB_WorkIssues.erase();
   }).then(function () {
      return DB_WorkIssues = new PouchDB(DBNAME_WorkIssues, { auto_compaction: true });
   }).then(function () {
      return ajaxCallForJsonTwoResults(URI_WorkIssues);
   }).then(function (args) {
      argsSaved = args;
      return args[1].reduce(function (promise, image) {
     return promise.then(function () {
        return resetImagesToPouch(image);
     });
      }, Promise.resolve(args)).then(function () {
     console.log('all done with images');
      });
   }).then(function (args) {
      return callBulkDocLoad(DB_WorkIssues, argsSaved[0]);
   }).then(function () {
      updateWorkIssuesJson();
      loadTaskList(false);

这是resetImagesToPouch功能:

    var resetImagesToPouch = function resetImagesToPouch(_ref) {
       var image = _ref.AttachmentFile,
           id = _ref.JobNumber,
           imageName = _ref.DocTitle;
       return DB_TaskImages.get(id, {
          attachments: true
       }).then(function (doc) {
          return DB_TaskImages.putAttachment(id, imageName, doc._rev, image, 'image/jpeg');
       }).catch(function (err) {
          if (err.status = '404') {
         // if this is a new document - add new attachment
         //var imageType = GetImageTypeFromBase64(image);
         return DB_TaskImages.putAttachment(id, imageName, image, 'image/jpeg');
          } else {
         throw err;
          }
       });
    };

在返回之前,循环只发生一次然后跳出来。有六个图像,循环现在发生了几次,但在完成所有循环之前不会执行resetImagesToPouch。

所以它是这样的:首先是减少,然后是#34;返回promise.then"和Promise.Resolve六次,然后它跳到"然后"然后它跳回到resetImagesToPouch,在那里它执行DB_TaskImages.get以查看这是否是此id的第一个图像,并且由于数据库为空,它将转到catch和404内部,如果是statment,然后是DB_TaskImages.putAttachment它跳转到函数末尾的位置,然后跳转到链末尾的catch,并显示错误:

err = r {status:404,name:" not_found",message:" missing",error:true,reason:" deleted"}

这是我们从.get通话中得到的错误,它给了我们404(我相信),所以我不知道它为什么会去那里。这似乎不是你从put得到的错误。所以它永远不会在链的最后一部分,因为它跳过它并且表中没有放置图像记录。

感谢。

在指出我错过了一个" =="之后,我更改了resetImagesToPouch()并修复了它,并添加了thens和catches to puts。这似乎解决了没有完成链条的问题。

    var resetImagesToPouch = function resetImagesToPouch(_ref) {
       var image = _ref.AttachmentFile,
           id = _ref.JobNumber,
           imageName = _ref.DocTitle;
       return DB_TaskImages.get(id, {
          attachments: true
       }).then(function (doc) {
          DB_TaskImages.putAttachment(id, imageName, doc._rev, image, 'image/jpeg').then(function () {
         console.log("Success insert of multiple attachment");
         return;
          }).catch(function () {
         console.log("Error in resetImagesToPouch: " + err);
         showMsg("Error in resetImagesToPouch: " + err);
          })
       }).catch(function (err) {
          if (err.status == '404') {
         // if this is a new document - add new attachment
         //var imageType = GetImageTypeFromBase64(image);
         DB_TaskImages.putAttachment(id, imageName, image, 'image/jpeg').then(function () {
            console.log("Successfull insert of multiple attachment");
            return;
         }).catch(function () {
            console.log("Error in resetImagesToPouch: " + err);
            showMsg("Error in resetImagesToPouch: " + err);
         });
          } else {
         console.log("At throw error");
         throw err;
          }
       });
    };

但它仍然没有插入任何图像。参数看起来很好,但是总是需要使用"未找到"以及上面的404错误。和"删除"。我能想到的唯一一件事(但不确定为什么会出现这种情况)是我在执行这些部分之前对这个数据库进行擦除(就像我对所有数据库所做的那样)。

          // TaskImages
       }).then(function () {
          if (DB_TaskImages != null)
         return DB_TaskImages.erase();
       }).then(function () {
          return DB_TaskImages = new PouchDB(DBNAME_TaskImages, { auto_compaction: true });

我为大约6个数据库执行此操作,因为我正在从服务器重新加载它们。我想知道循环中的.gets和.put是否可能导致问题?似乎没有多大意义。

我只是尝试了一些新的擦除并将其更改为销毁。这效果更好。与从不添加任何图像的擦除不同,这个将添加6个图像中的4个。它在其中两个中得到404错误,但不是说理由:"删除",它说原因:"缺少"。我认为这个问题是这些实际上是同一个ID的多个附件。但由于某些原因,当.get完成时,它没有找到记录,所以它做了一个没有修订的.put(采用了404路径)并在此时找到了记录并因为修订而给出了错误失踪。也许,当它第一次录制时,当第二张唱片出现时它还没有完成。

感谢。

我今天早些时候重新设计了resetImagesToPouch,因为我无法让旧版本工作。它总是起作用,但总有一些东西没有,而且我的时间已经不多了。擦除和丢失图像导致的404错误是一个问题。

我最终回到我的resetImagesToPouch是一个承诺,并且终于能够让它在没有跳跃的情况下工作,并且出于某种原因没有图像问题,只要我做了破坏而不是擦除。擦除不会保存任何东西。它刚刚回来了404失踪或404删除。我只是没时间试图找出原因。

以下是我今天下午终于完成的工作。

          // TaskImages
       }).then(function () {
          if (DB_TaskImages != null)
         return DB_TaskImages.destroy();
       }).then(function () {
          return DB_TaskImages = new PouchDB(DBNAME_TaskImages, { auto_compaction: true });

          // WorkIssues
       }).then(function () {
          if (DB_WorkIssues != null)
         return DB_WorkIssues.erase();
       }).then(function () {
          return DB_WorkIssues = new PouchDB(DBNAME_WorkIssues, { auto_compaction: true });
       }).then(function () {
          return ajaxCallForJsonTwoResults(URI_WorkIssues);
       }).then(function (args) {
          argsSaved = args;
          console.log("Before the reduce");
          return args[1].reduce(function (promise, image) {
         console.log("After the reduce and before the promise.then");
         return promise.then(function () {
            console.log("Inside the promise.then and before the resetImagesToPouch");
            return resetImagesToPouch(image).then(function () {
               console.log('Image written to Pouch successfully');
            }).catch(function (err) {
               console.log("Error in resetImagesToPouch with err: " + err);
            });
            console.log("After the resetImagesToPouch");
         });
         console.log("Before the Promise.resolve");
          }, Promise.resolve(args)).then(function () {
         console.log('all done with images');
          });
       }).then(function (args) {
          console.log("Before the callBulkDocLoad");
          if (argsSaved[2].length > 0) {
         console.log("Ajax issue with err: " + argsSaved[2][0]);
         msg = "Ajax issue with err: " + argsSaved[2][0];
          }
          return callBulkDocLoad(DB_WorkIssues, argsSaved[0]);
       }).then(function () {
          console.log("Before the updateWorkIssuesJson");
          updateWorkIssuesJson();
          loadTaskList(false);

还有resetImagesToPouch:

    function resetImagesToPouch(_ref) {
       var image = _ref.AttachmentFile,
        id = _ref.JobNumber,
        imageName = _ref.DocTitle;

       return new Promise(function (resolve, reject) {

          var rev;
          var imageType;

          // check if attachment already exists

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

         rev = doc._rev;    // Get the revision number since we are updating and adding attachment to existing doc.

         DB_TaskImages.putAttachment(id, imageName, rev, image, "image/jpeg").then(function () {
            console.log("Attachment added successfully");
            return;
         }).then(function () {
            resolve();
         }).catch(function (err) {
            reject(err);
         });
         return;
          }).catch(function (err) {
         if (err.status = '404') {      // if this is a new document - add new attachment
            //imageType = GetImageTypeFromBase64(image);
            DB_TaskImages.putAttachment(id, imageName, image, "image/jpeg").then(function () {
               console.log("Attachment added successfully");
               return;
            }).then(function () {
               resolve();
            }).catch(function (err) {
               reject(err);
            })
         }
          });
       });      // end promise
    }

它可能不是处理它的最佳方式,但它正在发挥作用。我现在对它的理解比较好,但仍然需要用它来处理我不喜欢的部分。比如在reduce中的部分,我还没有真正了解所有这些,并且当我有更多时间时会看到它。我确实得到了一些。但不确定为什么它会在所有resetImagesToPouch调用之前在所有图像的promise.then和Promise.resolve之间来回反弹。当我出城去复活节时,这将给我一些工作。

感谢所有帮助。

我怀疑没有它我会得到它。

1 个答案:

答案 0 :(得分:1)

使用array.reduce很简单,一旦你有一个有效的数组

let images = [
    { id: '111', imageName: 'fighter.jpg', image: 'aaaaaddddd' },
    { id: '111', imageName: 'horse.jpg', image: 'aaasdfssdaaddddd' },
    { id: '112', imageName: 'cat.jpg', image: 'aasdfaaadsdfsfdddd' },
    { id: '113', imageName: 'dog.jpg', image: 'aaasdfasfaaaddddd' },
    { id: '1234', imageName: 'apple.jpg', image: 'aaaasdfasaaddddd' }
]

重写resetImagesToPouch以正确返回承诺

let resetImagesToPouch = ({image, id, imageName}) => 
    DB_TaskImages.get(id, {
        attachments: true
    })
    .then((doc) => DB_TaskImages.putAttachment(id, imageName, doc._rev, image, 'image/jpeg'))
    .catch ((err) => {
        if (err.status = '404') { // if this is a new document - add new attachment
            //var imageType = GetImageTypeFromBase64(image);
            return DB_TaskImages.putAttachment(id, imageName, image, 'image/jpeg');
        } else {
            throw err;
        }
    });

现在,你要减少它的魔力

images.reduce((promise, image) => promise.then(() => resetImagesToPouch(image)), Promise.resolve())
.then(() => {
    console.log('all done');
});

如果ES2015 +吓到你了

var resetImagesToPouch = function resetImagesToPouch(_ref) {
    var image = _ref.image,
        id = _ref.id,
        imageName = _ref.imageName;
    return DB_TaskImages.get(id, {
        attachments: true
    }).then(function (doc) {
        return DB_TaskImages.putAttachment(id, imageName, doc._rev, image, 'image/jpeg');
    }).catch(function (err) {
        if (err.status = '404') {
            // if this is a new document - add new attachment
            //var imageType = GetImageTypeFromBase64(image);
            return DB_TaskImages.putAttachment(id, imageName, image, 'image/jpeg');
        } else {
            throw err;
        }
    });
};

现在,你要减少它的魔力

images.reduce(function (promise, image) {
    return promise.then(function () {
        return resetImagesToPouch(image);
    });
}, Promise.resolve()).then(function () {
    console.log('all done');
});

看着"链"在编辑过的问题中

}).then(function () {
    return ajaxCallForJsonTwoResults(URI_WorkIssues);
}).then(function (args) {
    // add return here
    return args[1].reduce(function (promise, image) {
        return promise.then(function () {
            return resetImagesToPouch(image);
        });
    }, Promise.resolve(args))
    .then(function () {
        console.log('all done with images');
        // pass on args down the chain
        return args;
    });
}).then(function (args) {
    return callBulkDocLoad(DB_WorkIssues, args[0]);
}).then(function () {

并且为了完整起见 - 在ES2015 +中

})
.then(() => ajaxCallForJsonTwoResults(URI_WorkIssues))
.then(([docs, images]) => 
    images
    .reduce((promise, image) => 
        promise.then(() => 
            resetImagesToPouch(image)),
        Promise.resolve()
    )
    .then(() => docs)
)
.then(docs => callBulkDocLoad(DB_WorkIssues, docs))
.then(() => {