2016-08-01 30 views
0

我不確定如何使用promises/bluebird充分實現我期望的控制流。什麼是一種明智的方式來構建我的控制流(承諾和循環)?

本質上,我有一個數據庫與X'任務'存儲,每個需要加載和順序執行。我不想同時運行多個任務,並且整個代碼必須無限期地繼續執行。

我已經用下面的代碼迄今取得這樣的:

export default function syncLoop() { 
    getNextTaskRunner().then((taskRunner) => { 
    if (taskRunner) { 
     taskRunner.startTask() 
     .then(syncLoop) 
     .catch((error) => { 
     throw new Error(error); 
     }); 
    } else { 
     syncLoop(); 
    } 
    }); 
} 

getNextTaskRunner()簡單地加載,並與數據庫中的下一個任務(計算值基於時間戳)解決。或者它用null解決(沒有任何可用的)。

taskRunner.startTask()在完整任務完成時使用null解析。

我已經被告知,它的結構(遞歸/ w承諾)的方式可能導致堆棧問題運行一段時間後。

我也想過這樣做是把它重組爲類似:

let running = false; 
    setInterval(() => { 
    if (!running) { 
     running = true; 
     getNextTaskRunner().then((taskRunner) => { 
     if (taskRunner) { 
      taskRunner.startTask() 
      .then(() => { 
      running = false; 
      }) 
      .catch((error) => { 
      log.error(error); 
      }); 
     } else { 
      running = false; 
     } 
     }); 
    } 
    }, 5000); 

或者作爲另一種可能性,在使用某種形式的活動發射器?

task.on('complete', nextTask());

的思考和建議,將不勝感激!

回答

1

什麼堆棧問題?只要getNextTaskRunner是真正異步的(即它在某個時候將控制權交還給主循環,例如,如果它執行了異步io),那麼您編寫代碼的方式就沒有問題。在這種情況下,代碼中沒有遞歸。誰告訴你這是錯誤的。

雖然你可能想在某處添加一個setTimeout,所以你不會用你的數據庫氾濫請求。另外它會幫助你,如果getNextTaskRunner將不再同步(由於例如在內存緩存):

export default function syncLoop() { 
    setTimeout(() => { 
    getNextTaskRunner().then((taskRunner) => { 
     if (taskRunner) { 
     taskRunner.startTask() 
      .then(syncLoop) 
      .catch((error) => { 
      throw new Error(error); 
      }); 
     } else { 
     syncLoop(); 
     } 
    }); 
    }, 2000); 
} 
+0

getNextTaskRunner絕對是異步的。 感謝您的反饋,非常感謝! – kurt343