2017-08-14 630 views
0

我想要做的事情可能不可能在節點js中,但在放棄之前我想獲得其他意見。setInterval並等待某些條件

我有一個線程正在執行產品的設置。爲了爭論,讓我們稱之爲'主'線。我希望在產品設置過程中可能發生的所有錯誤都被'主'線程捕獲。如果設置成功,那麼在我知道設置已成功之前,我不希望「主」線程完成。

產品設置過程中的一個步驟涉及在客戶的AWS賬戶中創建CloudFormation堆棧。 AWS的功能是createStack。這個函數只是開始創建堆棧的過程。如果你使用await來調用這個函數,那麼在獲得返回值後,創建棧的過程仍然會運行。

還有另一個名爲describeStacks的AWS CloudFormation函數,可以用它來了解創建過程。我無法重複調用此方法(不需要在調用之間使用較大間隔),因爲AWS限制了我可以多次調用方法。

我希望能夠每分鐘調用一次該函數來檢查堆棧創建的進度,直到我可以確定安裝程序成功或失敗。但關鍵的是,我還希望'主'線程等到這個成功或失敗發生。

這是可能的節點JS?我是節點js的新手。請隨時告訴我,我正在濫用它,並且我正在以錯誤的方式思考這個問題。我懷疑我是。

解決方案:下面是爲我解決問題的代碼。由於託默勒格

function checkStackCreationProgress(params) { 
    return new Promise((resolve, reject) => { 
     const intervalId = setInterval(async() => { 
      try { 
       const result = await checkProgress(params); 

       switch(result.status) { 
        case 'IN_PROGRESS': break; //do nothing 
        case 'COMPLETE': clearInterval(intervalId); resolve(result); break; 
        case 'FAILED': clearInterval(intervalId); reject(result); break; 
       } 
      } 
      catch(error) { 
       clearInterval(intervalId); 
       reject(error); 
      } 
     }, 
     60000); 
    }) 
    .then(() => { 
     return; 
    }) 
    .catch(error => { 
     throw new SetupFailedError(`Failed to create ...`, error); 
    }); 
} 

此功能不會返回,直到安裝已成功完成或失敗

回答

1

如果您使用的await,然後創建堆棧的過程中依然會後,在運行調用這個函數獲得返回值。

不要用await調用它,這會阻塞該線程。

異步函數返回Promises,您可以鏈接它們並在此期間做其他事情。

所以不是

try { 
    var result = await createStack({some: params)); 
    // work with result 
} catch (ex) { 
    // handle error 
} 

createStack({some: params)).then(function (result) { 
    // work with result 
}).catch(function (error) { 
    // handle error 
}); 

第二種形式是無阻塞的,你可以做任何工作,在此期間。例如:

var checking = setInterval(function() { 
    // check/output for the stack status... 
}, 60000) 

createStack({some: params)).then(function (result) { 
    clearInterval(checking); 

    // work with result 
}).catch(function (error) { 
    clearInterval(checking); 

    // handle error 
}); 

console.log("Stack is being created, hang on..."); 
+0

謝謝你的回覆。我不相信這會做我想做的事。我需要在setInterval(describeStacks)中調用的函數也返回一個承諾,並且這是承諾我需要檢查結束條件。在此引發的任何錯誤都不會在setInterval之外捕獲。我錯了嗎? – SiLaf

+1

那麼,'setInterval()'只是一種概述,你可以在單個節點線程中並行執行所有這些。當'createStack()'運行時,沒有任何東西可以讓你處理更多的承諾。我簡單地假設'createStack()'返回操作的結果,'describeStacks()'僅僅用於報告進度,所以我保持簡單。 – Tomalak

+1

這裏有多個帖子解釋瞭如何實現「重試直到成功」 - 帶有承諾的模式。 [這是一個](https://stackoverflow.com/questions/38213668/promise-retry-design-patterns)和[這裏是另一個](https://stackoverflow.com/questions/26694467/promises-repeat-operation-until - 成功),你會發現更多,如果你環顧四周。具體的實現在圖書館中有所不同,但它可以完成,並不像起初看起來那麼困難。 – Tomalak