0

I'm implementing a simple logger in JavaScript that collects messages when certain events happen on the page (a button is clicked, DOM is changed, etc), and all the collected messages are periodically sent to the server using AJAX calls:

var Logger = function () {
    var messages = [];

    var flush = function () {
        if (messages.length) {
            $.post("receive-logs.php", { messages: messages.toString() });
            messages = [];
        }
    };

    return {
        init: function () {
            setInterval(flush, 5000);
        },
        addMessage: function (message) {
            messages.push(message);
        }
    };
}();
Logger.init();

// Usage example: 
// $("#button1").on("click", function () { Logger.addMessage("button1 clicked"); })

The thing I am concerned with in this implementations is whether messages can get "lost" if addMessage is called after $.post but before messages = [].

In many articles I've read that JavaScript runs in a single-threaded environment, and thus developers never need to worry about stuff like locking or concurrency control. Which is confusing, because I see no reason why the situation I described above is impossible.

My question is: is the message loss possible in this case and how do I avoid it?

geppertuo
  • 3
  • 2
  • 1
    That shouldn't be a problem. What I'd worry about is the ambiguity introduced by smashing the whole array of messages into a single string. Messages with commas in them will look like separate messages. – Pointy Apr 22 '16 at 13:53
  • As there's only one user script execution at a time, no code can change the messages array between the two lines of code. There's no risk here. – Denys Séguret Apr 22 '16 at 13:54
  • Is this question a duplicate of https://stackoverflow.com/questions/2734025/is-javascript-guaranteed-to-be-single-threaded?rq=1 ? – Denys Séguret Apr 22 '16 at 13:54
  • _"My question is: is the message loss possible in this case and how do I avoid it?"_ You could call `messages = []` at `$.post()` complete callback. – guest271314 Apr 22 '16 at 13:56
  • You could set your `messages = [];` in the success portion of the `.post` call (see https://api.jquery.com/jQuery.post/) to ensure it is done as quickly as possible. Alternatively, and likely safer, you could set a variable `resetMessages = true;` (set to false on initialization) before your post, and set `messages = [];` in your `addMessage` function if it is true. – yk11 Apr 22 '16 at 14:03
  • @guest271314, if I do this, what happens if a new message arrives after `$.post` is called, but before the complete callback fires? – geppertuo Apr 22 '16 at 14:05
  • If only a single message is posted to server what is purpose of using an array? Not certain what Question is? Which portion of `js` at Question is not returning expected results? – guest271314 Apr 22 '16 at 14:16
  • @guest271314, I'm posting an array (action 1) and then at the next line emptying it (action 2). Plus I have a function that can be called by external code at any time that modifies this array (action 3). My question is: it is possible in JavaScript that (action 3) is executed between (action 1) and (action 2). I've no idea how to test it, it's just my guess, the code above isn't returning unexpected results for me. I'm asking if it can _potentially_ return unexpected results. – geppertuo Apr 22 '16 at 15:04
  • @geppertuo You should be able to test approaches at jsfiddle http://jsfiddle.net or plnkr http://plnkr.co or stacksnippets see http://meta.stackoverflow.com/questions/288902/does-stack-overflow-have-an-echo-page-to-test-ajax-requests-inside-a-code-sni/ – guest271314 Apr 22 '16 at 15:21

0 Answers0