2

Hey guys so I've been so confused hearing that the callback of a promise executed asynchronously I'm starting to get to a point where I'm not sure if I'm right or wrong.

From what I know the golden rule of Javascript is that it's single-threaded in other words Javascript executes code SYNCHRONOUSLY ONLY ! So now I will explain the way I understand how promises work and please tell me if I'm correct.

var p = new Promise((resolve)=>{resolve('Hello StackOverflow !');})

Ok, so the first that's happening is that we are creating a promise.

And basically, it runs the callback we passed as an argument, and the resolve is doing is three things!

1.it sets the [[PromiseState]] to fulfilled

  1. it will set the [[PromiseValue]] to whatever value put in the resolve

  2. it checks if we already created the callback from then and if we already made the callback it will push the callback to the Microtask and when the whole execution context will be popped off the stack the event loop will take place and the callback will run.

    p.then((cur)=>{console.log(cur);})

Now then is running and what it does is 2 things

1.it will save the callback we made somewhere so the resolve function will have access to the callback

  1. it will check if [[PromiseState]] is no longer pending and if it's no longer in pending state it will push the callback into the Microtask and once again after the whole execution context will be popped off the stack the event loop will take place and the callback will run

Here I've made a mini promise function of my own it doesn't contain all the features like reject finally catch but it's enough to get a basic idea.

(function(){
    const PENDING = 'Pending', FULFILLED = 'Fulfilled';
  var Promise = function(executor){
    this.status = PENDING;
    this.callback = null;
    this.value = null;
    var resolve = (value)=>{
      this.value = value;
      this.status = FULFILLED;
      runCallBackIF.call(this); 
    };
    executor(resolve);
  };

  Promise.prototype.then = function(fn){
        this.callback = fn;
    runCallBackIF.call(this);   
  };
  
  var runCallBackIF = function(){
    if(typeof this.callback === 'function'){
        if(this.status === FULFILLED){
        queueMicrotask(()=>{this.callback(this.value)});
      }
    }
  };
  
  window.Promise = Promise;
})();

var p = new Promise(function(resolve){resolve('Hello Stackoverflow !')});

p.then(function(cur){
    console.log(cur);
});

So, am I right or completely wrong and Javascript promises absolutely don't work that way

I hope to hear it from you because I get so confused when people say that the promises callback executes asynchronously.

FZs
  • 16,581
  • 13
  • 41
  • 50
Nadav Shlush
  • 47
  • 1
  • 8
  • 1
    The `queueMicroTask()` portion of what you've outlined is the general idea for how it works. When the promise becomes fulfilled, it queues as a microtask any `.then()` handlers that are currently registered and those will run immediately AFTER the current set of Javascript finishes executing. That's what gives a `.then()` handler its behavior that it always runs "asynchronously". You can see that if you run this simple code: `Promise.resolve("hi").then(value => console.log("hi")); console.log("goodbye");` which will log "goodbye" first before "hi". – jfriend00 Aug 07 '21 at 16:46
  • 3
    As you know there are lots more implementation details not implemented here, but one significant one related to `.then()` is that both `.then()` and `.catch()` callbacks would be stored as an array of listeners as there can be more than one of each. And, `.then()` optionally takes two listeners `.then(fnThen, fnCatch)`. And, you have to catch exceptions thrown in listeners when they are called so you can act accordingly. And, you have to be able to chain promises if a `.then()` handler returns a new promise and `.then()` and `.catch()` both return a new promise when then methods called, etc... – jfriend00 Aug 07 '21 at 16:54
  • 1
    If you want to see how well your implementation is doing, run the Promises/A+-compliance tests [on github](https://github.com/promises-aplus/promises-tests). There are many nuances. One challenging thing is that a `then()` should return a new promise, and it should resolve with the value that its callback argument returns, taking into account that it could be a promise, to which it should then lock-in. I did this exercise once, and posted it as an answer [here](https://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/42057900#42057900). – trincot Aug 07 '21 at 17:01
  • Hey try watching this video: https://www.youtube.com/watch?v=8aGhZQkoFbQ – h-sifat Aug 07 '21 at 17:13
  • There are some minor corrections to your description. For example, microTasks run before the event loop. So, *push the callback to the Microtask and when the whole execution context will be popped off the stack the event loop will take place and the callback will run* isn't quite described correctly. The microTasks will run after the current execution context is done, but they will run before the event loop. In a simplistic description, people tend to think of this as part of the event loop, but technically, microTasks run before the event loop. – jfriend00 Aug 07 '21 at 17:30
  • how the microtask run before the event loop ? the event loop is just handler for all those tasks. the event loop is what sends the macro and micro tasks to the Javascript Engine so it will run those tasks. microtask just have higher priority than the macro so it will run before. – Nadav Shlush Aug 07 '21 at 17:58
  • I think this could explain what @jfriend00 meant: According to [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) - _A microtask is a short function which is executed after the function or program which created it exits and only if the JavaScript execution stack is empty, but before returning control to the event loop being used by the user agent to drive the script's execution environment._ – Karin C Aug 07 '21 at 22:45
  • @NadavShlush - It is mostly just semantics about what you consider part of the event loop, but most people describe the event loop as handling things outside of the actual ECMAScript specification that are part of the host environment such as timers and networking and that's the same way that the MDN description of microtasks describes it too. The ECMAScript specification does describe a [PromiseJob](https://262.ecma-international.org/11.0/#sec-jobs). And, existing implementations such as web browsers and nodejs execute pending PromiseJobs before any host activities in the event loop. – jfriend00 Aug 08 '21 at 00:50

0 Answers0