Search code examples
javascriptpromiserace-conditiondeferreddeferred-execution

Why in javascript deferred callbacks don't create race conditions?


So I wanted write something similar to this snipped from IndexedDB docs:

var req;
var store = getStore();
req = store.count();
req.onsuccess = function(evt) {
  console.log("success: " + evt.result);
};
req.onerror = function(evt) {
  console.error("add error", this.error);
};

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

And started to wonder why javascript allow definitions of (deferred?) callbacks after a call and why it doesn't cause race conditions? Can someone share some light please?

So, how does javascript make sure that async call doesn't get executed before callback is assigned?

Thanks!


Solution

  • JS is single threaded, so the actual execution order of your current code is as follows:

    store.count();              // trigger some async code
    req.onsuccess; req.onerror; // attach the callbacks
                                // some other code in the same function/scope may follow
    
                                // your code is finished; next item from event queue is executed
    
    store.count();              // the async part gets executed
    req.onsuccess();            // after the async part (or within it) 
                                // one of your callbacks gets executed.
    

    So you can see, it does not really matter, when you attach your callbacks, as long as you do it, before the current function is finished and the JS event queue looks for the next code block to execute.


    With respect to your comment: No, parse and execution time are not identical in modern JS engines. The engine does compile your code and then executes it. (There are some exceptions, where a fallback to the old interpreter-style is used, but that should not be relevant in most cases).