簡體   English   中英

承諾while(true)循環/等待承諾解決

[英]Promises in while(true) loop / waiting for promise to resolve

我想在node.js中編寫一個小型的worker應用程序。
此應用程序將從AWS-SQS讀取,以某種方式處理數據,並將其吐出到另一個AWS-SQS。
到目前為止我寫了:

while(true){
    readFromQueue()
    .then(transform)
    .then(writeToQueue);
}

function transform(data) {
    console.log("> transforming...");
    //transformation logic
    return data;
}

//TODO: need to remove message from queue after read!
function readFromQueue() {
    // var params = {
    //   QueueUrl: 'STRING_VALUE',
    //   WaitTimeSeconds: 2
    // };

    // return new Promise(function(resolve, reject) {
    //  sqs.receiveMessage(params, function(err, data) {
    //      if (err) reject(err);
    //      else     resolve(data);
    //  });
    // });
    return new Promise(function(resolve, reject) {
        console.log("> reading from queue...");
        resolve({ data : "world" });
    });
}

function writeToQueue(data) {
    // var params = {
    //  MessageBody: data,
    //  QueueUrl: 'STRING_VALUE',
    // };
    // sqs.sendMessage(params, function(err, data) {
    //  if (err) console.log(err, err.stack);
    //  else     console.log(data);
    // });
    console.log("> writing to queue...");
    console.log(">> " + data);
}

正如您所看到的,所有內容都是為AWS設置的,但是當我暫時在本地運行它時,我會在內部有一些模擬內容,直到我真正得到我的轉換邏輯測試等...
我遇到的問題是:

  • AWS-SQS API是異步的,需要回調。 我用承諾包裝它,因為我更喜歡承諾回調。 然而,我想知道我是否應該阻止它並使其同步而不是異步(由於下面的原因,但可能是無關的)。
  • 當我運行它時,我只能看到“從隊列中讀取...”輸出,它幾乎就像沒有執行“transform”和“writeToQueue”...
  • 但是,如果我注釋掉while循環(所以腳本只運行一次),我可以看到所有3個步驟的輸出。

我做錯了什么? 我可以理解,因為promises是異步的,我的while循環會變得瘋狂並創建數千個,所以這讓我感到擔憂......但是我想在前一次read-> transform-> write完成之后啟動另一個循環。 我應該在這里使用其他一些模式嗎? 或者只是阻止並等待readFromQueue結束...

- 編輯 -
如果沒有包裝,它確實會執行所有內容(true):

readFromQueue()
        .then(transform)
        .then(writeToQueue);

我也明白,因為while(true)正在執行,它將基本上阻塞線程,因此未解決承諾。 那么有辦法嗎?

我正在回到我的setInterval方式。 我知道你說閱讀隊列必須在寫完后立即開始,但是如果你問我,10ms就沒有太大的延遲了。

function someFunc(){
    if(readingQueue)    return;
    readingQueue = true;
    return readFromQueue()
      .then(transform)
      .then(writeToQueue)
      .catch(someErrorHandler)
      .then(function(){
        readingQueue=false;
      })
} 

var readingQueue = false;
setInterval(someFunc, 10);

在評估了這里的所有答案后,我嘗試了deasync ,這工作做得很好:)
不過,我決定采用上面的mido22答案,因為我不想要一個擺弄節點事件循環的插件。

而不是這個:

while(true){
    readFromQueue()
    .then(transform)
    .then(writeToQueue);
}

你不能使用遞歸函數嗎? 像這樣的東西:

function getData(){
    return readFromQueue()
        .then(transform)
        .then(function(data){
            writeToQueue(data);
            getData();
        });
}

getData(); //Just to get it starting.

我也遇到了類似的問題(請參閱setTimeout問題,試圖等待執行異步 )。

我已經學會了在javascript中要避免同步模式的教訓,所以我認為你的代碼可以用類似的東西重寫:

function queueLooping(loopExitConditionPromise) {

    var blockingGuard = { done: false };

    loopExitConditionPromise.then(function () {
        blockingGuard.done = true;
    });

    return loopingSequence;

    var loopingSequence = function() {
        readFromQueue()
            .then(transform)
            .then(writeToQueue);
        if(!blockingGuard.done) 
            loopingSequence();
        else
            return;
    };

    var readFromQueue = function () {
        console.log("> reading from queue...");
        // ...
    }

    var transform = function (data) {
        console.log("> transforming...");
        // ...
    }

    var writeToQueue = function (data) {
        console.log("> writing to queue...");
        // ...
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM