while(true)循环/等待承诺解决

时间:2015-08-20 09:28:56

标签: javascript node.js amazon-web-services promise

我想在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是异步的,需要回调。我用承诺包装它,因为我更喜欢承诺回调。不过,我想知道我是否应该阻止它并使其同步而不是异步(由于下面的原因,但可能不相关)。
  • 当我运行时,我只能看到"从队列中读取..."输出,几乎就好像"转换"和#34; writeToQueue"没有执行...
  • 但是,如果我注释掉while循环(所以脚本只运行一次),我可以看到所有3个步骤的输出。

我做错了什么?我可以理解,因为promises是异步的,我的while循环会疯狂并创建数千个,所以这让我感到担忧......不过我希望在前一次read-> transform-> write完成后启动另一个循环。我应该在这里使用其他一些模式吗?或者只是阻止并等待readFromQueue结束......

- EDIT--
它确实执行了所有内容,如果没有包装在while(true):

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

我也明白,因为while(true)正在执行,它将基本上阻塞线程,因此未解决承诺。那么有办法吗?

4 个答案:

答案 0 :(得分:4)

我正在回归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);

答案 1 :(得分:0)

在评估了here中的所有答案后,我尝试了deasync,这很好地完成了工作:) 不过,我决定采用上面的mido22答案,因为我不想要一个摆弄节点事件循环的插件。

答案 2 :(得分:0)

而不是:

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.

答案 3 :(得分:0)

我也遇到过类似的问题(见setTimeout issue trying to wait for execution of async)。

我已经从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...");
        // ...
    }
}