0

Here is my code:

for (var i = 0; i < items.length; i++) {
    doSomeWork('Company","{message : "message"}');
}

doSomeWork = function (companyIdentifier,item) {
    var serialisedMessage = new serialisedMessageWithMetadata(item);

    //I want this to block until the callback inside send is fired.
    send(companyIdentifier, serialisedMessage.getJSON());
}

send = function (queueId, msg) {
    var sqsQueueUrl = this.createQueueUrl(queueId);

    var sqsParams = {
        MessageBody: JSON.stringify(msg),
        QueueUrl: sqsQueueUrl
    };

    sqs.sendMessage(sqsParams, function (err, data) {
        if (err) {
            console.log('ERR', err);
        }
        else {
            console.log(data);
        }
    });
}

I want my for loop to wait on the callback in sendMessage being fired. Looking through some articles on Google, I started to think Promises is what I needed, but this seems really complicated way of simply block a function (and I couldn't get the examples working either!)

I suspect it's something basic I missing, and was hoping for something like "await".

Any help would be appreciated.

2 Answers2

1

You cannot block Javascript waiting for an async operation to complete. It simply does not work that way. If you want to serialize your messages so one is sent, successful response is received, then the next one is sent, then you will have to specifically write code for sequential async operation. There are a number of approaches.

Here are some examples of solving this problem:

Making async javascript task in a loop

How to synchronize a sequence of promises?

Questions from the synchronous node.js

Here's one idea how to restructure your code to make it work sequentially:

function doAllWork(items, companyIdentifier) {
    var cntr = 0;

    function send(queueId, msg, done) {
        var sqsQueueUrl = this.createQueueUrl(queueId);

        var sqsParams = {
            MessageBody: JSON.stringify(msg),
            QueueUrl: sqsQueueUrl
        };

        sqs.sendMessage(sqsParams, function (err, data) {
            if (err) {
                console.log('ERR', err);
            }
            else {
                console.log(data);
            }
            done(err, data);
        });
    }

    function doSomeWork() {
        // if still more do do, then do the next one
        if (cntr < items.length) {
            var serialisedMessage = new serialisedMessageWithMetadata(items[cntr++]);

            //I want this to block until the callback inside send is fired.
            send(companyIdentifier, serialisedMessage.getJSON(), function(err, data) {
                if (!err) {
                    // do next iteration
                    doSomeWork();
                }
            });
        }
    }
}

doAllWork(items, 'Company","{message : "message"}');
Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

By adding a callback to your send function and using npm async module for blocking your for loop. Something like this?

  async.forEach(items,function(item,innerCallback){
        var serialisedMessage = new serialisedMessageWithMetadata(item);

        //I want this to block until the callback inside send is fired.
        send(companyIdentifier,      serialisedMessage.getJSON(),function(err,res){
            if(!err){
                console.log("SUCCESS");
            }else{
                console.log("SUCCESS");
            }   
            innerCallback();
        });
    },function(err,res){
        console.log("Finsied sending msgs");
    })

    send = function (queueId, msg,callback) {
        var sqsQueueUrl = this.createQueueUrl(queueId);

        var sqsParams = {
            MessageBody: JSON.stringify(msg),
            QueueUrl: sqsQueueUrl
        };

        sqs.sendMessage(sqsParams, function (err, data) {
            if (err) {
                console.log('ERR', err);
                callback(true,"ERROR")
            }
            else {
                console.log(data);
                callback(null,data)
            }
        });
    }
zoram
  • 512
  • 6
  • 16