【问题标题】:How to use promise inisde forEach to check if forEach is completed?如何在 forEach 中使用 promise 来检查 forEach 是否完成?
【发布时间】:2017-08-29 16:43:48
【问题描述】:

这是我第一次尝试使用 Promise。当forEach 完成后,我想调用另一个函数进行进一步处理,使用forEach,它只打印一次insertIDBEvents,下一次调用它不会打印。

forEach使用promise的正确方法是什么?

nodeCtrl.js

    var ctr = 0;
    var insertIDBEvents = [];
    data.forEach(function(element, index, array) {
        event = JSON.parse(element.variables.event.value);
        if (typeof element.variables.caseIdFound !== 'undefined') {
            //asynchronous(function(data){
            Promise.all(array)
                .then(function(element) {
                    ctr++;
                    console.log("caseIdFound boolean", element.variables.caseIdFound.value);
                    insertIDBEvents.push(element);
                    console.log(insertIDBEvents);
                    if (ctr === array.length) {
                        console.log('IDBinsert', JSON.stringify(insertIDBEvents));
                    anotherFunction(insertIDBEvents)
                    }
                })

        }

    });

anotherIDBEvents (data) {
   // do something with data
}

【问题讨论】:

    标签: javascript node.js foreach promise


    【解决方案1】:

    Promise.all 与迭代一起使用的方法是将您的元素数组映射到一个promise 数组,该数组执行与这些元素相关的必要异步操作,然后将该promise 数组传递给Promise.all

    所以这是一个总体思路:

    Promise.all(
      arrayOfElements.map(
        element => (
          functionThatReturnsAPromise(element)
        )
      )  
    )
    .then(results => {
      // ...
    })
    

    【讨论】:

    • 我只想在 if 条件下应用 Promise,并且该数组仍在由 forEach 处理
    • @hussain 不能那样工作,你不能那样混合同步和异步代码。
    【解决方案2】:

    重新排列您的代码,使Promise.all 在外面。此外,您的数组的值需要是 Promises。

    这有点难说,因为上面的代码显然不起作用,但我想你会想要映射你的数据数组,让每个元素运行一个承诺,然后将所有这些转储到 Promise.all .

    类似这样的:

    var ctr = 0;
    var insertIDBEvents = [];
    
    Promise.all(data.map(element => {
      event = JSON.parse(element.variables.event.value);
    
      if (typeof element.variables.caseIdFound !== 'undefined') { 
        ctr++;
        console.log("caseIdFound boolean", element.variables.caseIdFound.value);
        insertIDBEvents.push(element);
        console.log(insertIDBEvents);
        if (ctr === array.length) {
          console.log('IDBinsert', JSON.stringify(insertIDBEvents));
          anotherFunction(insertIDBEvents)
        }
      }
    })).then(() => {
      anotherIDBEvents(data);
    });
    

    【讨论】:

    • 一些事件有element.variables.caseIdFound未定义的值我不想将这些事件推送到另一个函数,所以我关心的只是推送对另一个函数有价值的事件,其余事件将在 Promise.all 中处理其他一些逻辑
    • @hussain 您可以在调用 map 函数之前添加类似.filter() 的内容来过滤掉数据。
    【解决方案3】:

    您可能希望首先构建您的承诺数组,使用条件过滤,然后将数组传递给Promise.all(),或者另一种常见的方法是构建一个元素数组并使用Promise.map()(如果您使用的库支持it),为每次迭代执行相同的代码,而不是为每个元素实例化相同的 Promise。

    const anotherFunction = element => {
      // do something with data
      return element
    }
    
    const elements = data.map(element => {
      return !!element.variables.caseIdFound
    })
    
    Promise.map(elements, element => {
      return anotherFunction(element)
    }).then(res => {
      //handle resolution
    }).catch(err => {
      //handle exceptions
    })
    

    【讨论】:

      猜你喜欢
      • 2017-05-30
      • 1970-01-01
      • 2018-04-28
      • 2018-10-01
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 2021-01-13
      • 1970-01-01
      相关资源
      最近更新 更多