2017-09-05 94 views
1

我有事件流向下面的程序,所以基於事件的價值我觸發不同的承諾,所以我想檢查是否它的好主意在forEach內使用承諾。如何在forEach中調用promise?

以下代碼當我有element.variables.caseIdFound價值事件它永遠不會滿足條件。任何想法是什麼實施錯我對這些承諾是相當新的。以下代碼的任何示例都非常感謝。

camunda.js

var caseIdFound; 
    var processingCompleted; 

    function checkTicketNum(element) { 
     var EventCasesID; 
     var event; 
     var ticketNumber; 
     var CasesID; 
     var insertIDBEvents = []; 
     var event; 
     return new Promise(function(resolve, reject) { 
       event = JSON.parse(element.variables.event.value); 
       ticketNumber = event.body.raw.tkt; 
       CasesID = event.body.raw.CasesIDuuid; 
       controller.insertCase(ticketNumber, function(err, response) { 
        event.body.raw.LogIDuuid = generateUUID(); 
        if (response.length == 0) { 
         completeTask('TicketNotFOund',element.id); 
        } else { 
         EventCasesID = response[0].CasesID; 
         if(CasesID === EventCasesID) { 
          caseIdFound = true; 
          completeTask(element.id,caseIdFound); 
          processingCompleted = true; 
          resolve(processingCompleted); 
         } 

        } 
       }) 
     }); 


    } 

function postIDBCall(element) { 
    var event; 
    return new Promise(
     function(resolve, reject) { 
      event = JSON.parse(element.variables.event.value); 
      controller.insertTicketAndCase2(event.body.raw, function(err, response2) { 
       controller.insertTicketAndCase(event.body.raw, function(err, response1) { 
       completeTask(event.id); 
       console.log("InsertIDB Result Completed",element.id); 
       processingCompleted = true; 
       resolve(processingCompleted); 
       }) 
      }) 

    }); 
} 


    module.exports = { 
     checkTicketNum: checkTicketNum, 
     generateUUID: generateUUID, 
     completeTask: completeTask 
    }; 

promise.js

var camunda = require('./camunda'); 

    data.forEach(function(element) { 
     if (!element.variables.caseIdFound) { 
      camunda.checkTicketNum(element).then(function(processingCompleted) { 
       console.log('1st Box', processingCompleted); 
      }); 
     }else if(element.variables.caseIdFound) { 
         console.log('END BOX IF', element.variables.caseIdFound); 
         camunda.postIDBCall(element).then(function(processingCompleted){ 
          console.log('2nd Box', processingCompleted); 
         }); 
        } 
    }); 
+1

看一看['Promise.all()'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) –

+0

您應該創建一個承諾數組,然後使用Promise.all()並在那裏插入您的承諾數組。 –

+0

請注意,promise.all將並行處理所有內容,具體取決於您的承諾正在做什麼,這可能會導致問題。藍鳥有一個值得一看的併發選項的地圖。另外一個簡單的for循環與asyn/await混合也是一個想法。 – Keith

回答

2

編輯:感謝@Bergi的評論。有一個錯誤,你仍然需要Promise.all(),則()

這裏是@serendipity代碼ES8版本:

const data = [false, 10, 20, 30] 
const { checkTicketNum, postIDBCall } = require("./camunda") 
const result = data.map(async(pieceOfData) => { 
    return (!pieceOfData) ? 
     await checkTicketNum(pieceOfData) : 
     await postIDBCall(pieceOfData) 
}) 
Promise.all(result).then(x => { console.log(x) }) 

有了一些意見:

//fake data 
const data = [false, 10, 20, 30] 
    //destructuring to avoid camunda.functionName 
const { checkTicketNum, postIDBCall } = require("./camunda") 
    //map will return a table containing the result of your promises 
    //Logging within a foreach does not garuantee you that the order of the logs is the execution order. Therefore, you can log at the end. 
const result = data.map(async(pieceOfData) => { 
     //if(a){myVar=1} else if(!a){myVar=2} is not a good programing syntax. 
     //Consider if(a){myVar=1} else {myVar=2}, 
     //and even the ternary operator myVar = (a)?{1}:{2} 
     //here : 
     return (!pieceOfData) ? 
      await checkTicketNum(pieceOfData) : 
      await postIDBCall(pieceOfData) 
    }) 
    //finally lof the result. JSON.stringify will help with nested JSON 
Promise.all(result).then(x => { console.log(x) }) 

如果你想測試,這裏是一個假camun.js文件:

checkTicketNum = (x) => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve("This is the checkTicketNum for " + x) 
     }, 1000) 
    }) 
} 

postIDBCall = (x) => { 
    return new Promise((resolve, reject) => { 
     setTimeout(() => { 
      resolve(x + 1) 
     }, 1000) 
    }) 
} 

module.exports = { 
    checkTicketNum, 
    postIDBCall 
} 

編輯:好吧,爲了確保@Bergi告訴我什麼,我寫了一個完整的假庫,所以這裏是一個工作示例。我也對性能問題感到好奇,所以我測試了執行時間與異步/等待或承諾完全相同。

//CAMUN.JS 
 
checkTicketNum = (x) => { 
 
    return new Promise((resolve, reject) => { 
 
     setTimeout(() => { 
 
      resolve("This is the checkTicketNum for " + x) 
 
     }, 1000) 
 
    }) 
 
} 
 

 
postIDBCall = (x) => { 
 
    return new Promise((resolve, reject) => { 
 
     setTimeout(() => { 
 
      resolve(x + 1) 
 
     }, 1000) 
 
    }) 
 
} 
 

 
//module.exports = { 
 
// checkTicketNum, 
 
// postIDBCall} 
 

 

 

 
//--------------------------// 
 

 

 

 

 

 
//MAIN FILE 
 

 
//destructuring to avoid camunda.functionName 
 
//const { checkTicketNum, postIDBCall } = require("./camunda") 
 

 

 
//fake data 
 
const data = [false, 10, 20, 30] 
 

 
console.time("await") 
 
const resultAwait = data.map(async(pieceOfData) => { 
 
    return (!pieceOfData) ? 
 
     await checkTicketNum(pieceOfData) : 
 
     await postIDBCall(pieceOfData) 
 
}) 
 
Promise.all(resultAwait).then(x => { 
 
    console.timeEnd("await") 
 
    console.log("Await result : " + JSON.stringify(x)) 
 
}) 
 

 

 
console.time("promiseAll") 
 
const resultPromises = [] 
 
data.map((pieceOfData) => { 
 
    return (!pieceOfData) ? 
 
     resultPromises.push(checkTicketNum(pieceOfData)) : 
 
     resultPromises.push(postIDBCall(pieceOfData)) 
 
}) 
 
Promise.all(resultPromises).then(x => { 
 
    console.timeEnd("promiseAll") 
 
    console.log("Promise result : " + JSON.stringify(x)) 
 
})

+0

我想你忘了'await Promise.all'的某處? – Bergi

+0

**等待**的要點是表中充滿了承諾的結果,而不是承諾本身。一旦承諾返回,表格將被填充。 ** await **的想法是允許您在Javascript中僞造同步代碼。 –

+0

嗯,沒有。結果表中充滿了代碼中的承諾。 – Bergi

0

這是我怎麼樣在一個循環中使用承諾

let data = [10,20,30]; 
let promises = []; 

data.forEach(function (eachData) { 
    let promise = new Promise((resolve,reject) => { 
     setTimeout(function() { 
      let newData = eachData + 10; 
      resolve(newData) 
     }, 1000) 
    }); 

    promises.push(promise); 
}); 

Promise.all(promises).then((data) => { 
    console.log(data) //returns [20,30,40] 
}); 

基本上什麼情況是,每一個承諾你在一個循環中運行,你將這個承諾推入一個數組中,並在Promise.all()的參數內部注入promises數組。它可以被用來作爲自我承諾,所以.then()函數是可能的。數據按順序返回到promises數組中,順序不是resolve()

+2

你應該使用'map'而不是'[]'+'forEach' +'push' – Bergi

+0

@Bergi你可以但爲什麼要這樣? – forJ

+0

更簡單 - 更安全 - 更短 - 更具可讀性 - 更快 - 我可以繼續... – Bergi