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

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

本文关键字:承诺 等待 解决 true 循环 while      更新时间:2023-09-26

我想用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是异步的,它需要一个回调。我用promise包装了它,因为比起回调,我更喜欢promise。然而,我想知道我是否应该阻止它并使其同步而不是异步(原因如下,但可能是无关的)。
  • 当我运行这个,我只能看到"读取队列.."输出,它几乎就像"转换"answers"writeToQueue"没有执行…
  • 然而,如果我注释掉while循环(这样脚本只运行一次),我可以看到所有3个步骤的输出。

我做错了什么吗?我可以理解,因为承诺是异步的,我的while循环会疯狂地创建成千上万个承诺,所以这让我很担心……尽管如此,我还是想在之前的read->transform->write操作完成后启动另一个循环。这里还有什么我应该用的句型吗?或者只是阻塞并等待readFromQueue结束…

——编辑——
如果没有使用while(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);

而不是:

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.

在评估了这里的所有答案后,我尝试了deasync,它做得很好:)
尽管如此,我还是决定使用上面的mido22答案,因为我不想要一个干扰节点事件循环的插件。

我也遇到了类似的问题(参见setTimeout问题试图等待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...");
        // ...
    }
}