javascript - promise 从阵列顺序触发

标签 javascript promise

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

我有一个承诺,可以做所有这一切,并且每次都需要调用,但是我似乎无法找出执行此操作的最佳方法。在线上的某些想法正在使用“减少”功能,但不确定其工作原理。

代码是:

    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]用于第一个承诺,并将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。

因此,它是这样的:先执行reduce,然后执行“ return promise.then”和Promise.Resolve六次,然后跳转到“ then”,然后跳回到一次resetImagesToPouch,在该处执行DB_TaskImages。看看这是否是该ID的第一张图片,并且由于数据库为空,因此转到catch并在404 if语句内,然后进入DB_TaskImages.putAttachment,在该处跳转到函数末尾,然后转到在链的末尾捕获到错误:

err = r {状态:404,名称:“ not_found”,消息:“ missing”,错误:true,原因:“ deleted”}

那是我们从.get调用中得到的错误,该错误给了我们404(我相信),所以我不知道它为什么去了那里。这似乎不是看跌期权所带来的错误。因此,它永远不会做链的最后一部分,因为它跳过了它,并且表中没有图像记录。

谢谢。

在指出我遗漏了“ ==”之后,我更改了resetImagesToPouch()并修复了该问题,然后添加了thens和catchs到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和.puts是否可能引起此问题?似乎没有多大意义。

我只是尝试了一些新的擦除操作,并将其更改为销毁。这样效果更好。不同于永远不会添加任何图像的擦除,此擦除将添加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之间来回反弹。当我在复活节外出时,这将为我提供一些工作。

感谢您的所有帮助。

我怀疑如果没有它我是否会解决这个问题。

最佳答案

一旦有了有效的数组,使用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;
        }
    });


现在,您让reduce做神奇吧

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;
        }
    });
};


现在,您让reduce做神奇吧

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(() => {

关于javascript - promise 从阵列顺序触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43319866/

相关文章:

javascript - 如何将 promise 结果传递给外部函数?

javascript - 如何在执行函数之前加载一些图像

javascript - 浏览器返回在页面本身之前作用于嵌套的 iframe - 有没有办法避免它?

javascript - 更新firebase数据后的回调

AngularJS 资源 promise

javascript - Ember.js 1.0rc6 - 未定义 RSVP

javascript - React fetch 返回空值

javascript - 以创建者用户身份单击按钮时运行函数 - Google 电子表格

javascript - AngularJS 应用程序中的 Protractor 和 ng-repeat

javascript - 多级转发引用 [Typescript/React]