0

based on the easy implementation of Promise: https://www.promisejs.org/implementing/

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {
   
   //  <-----------how can these two local variable maintain state between function calls?
   var state = PENDING;     
   var value = null;
   //

   // store sucess & failure handlers
   var handlers = [];

   function fulfill(result) {
      state = FULFILLED;
      value = result;
      handlers.forEach(handle);
      handlers = null;
   }

   function reject(error) {
      state = REJECTED;
      value = error;
      handlers.forEach(handle);
      handlers = null;
   }

   function resolve(result) {
      try {
         var then = getThen(result);
         if (then) {
            doResolve(then.bind(result), resolve, reject)
            return
         }
         fulfill(result);
      } catch (e) {
         reject(e);
      }
   }

   function getThen(value) {
      var t = typeof value;
      if (value && (t === 'object' || t === 'function')) {
         var then = value.then;
         if (typeof then === 'function') {
            return then;
         }
      }
      return null;
   }

   function handle(handler) {
      if (state === PENDING) {
         handlers.push(handler);
      } else {
         if (state === FULFILLED &&
            typeof handler.onFulfilled === 'function') {
            handler.onFulfilled(value);
         }
         if (state === REJECTED &&
            typeof handler.onRejected === 'function') {
            handler.onRejected(value);
         }
      }
   }

   this.done = function (onFulfilled, onRejected) {
      // ensure we are always asynchronous
      setTimeout(function () {
         handle({
            onFulfilled: onFulfilled,
            onRejected: onRejected
         });
      }, 0);
   }

   this.then = function (onFulfilled, onRejected) {
      var self = this;
      return new Promise(function (resolve, reject) {
         return self.done(function (result) {
            if (typeof onFulfilled === 'function') {
               try {
                  return resolve(onFulfilled(result));
               } catch (ex) {
                  return reject(ex);
               }
            } else {
               return resolve(result);
            }
         }, function (error) {
            if (typeof onRejected === 'function') {
               try {
                  return resolve(onRejected(error));
               } catch (ex) {
                  return reject(ex);
               }
            } else {
               return reject(error);
            }
         });
      });
   }

   doResolve(fn, resolve, reject);    // <-----------------partA
}

function doResolve(fn, onFulfilled, onRejected) {
   var done = false;
   try {
      fn(function (value) {
         if (done) 
            return
         done = true
         onFulfilled(value)
      }, function (reason) {
         if (done) 
            return
         done = true
         onRejected(reason)
      })
   } catch (ex) {
      if (done) return
      done = true
      onRejected(ex)
   }
}


let promise = new Promise(function (resolve, reject) {
   resolve(1);
}).then(result => console.log(result * 2),reason => { console.log(reason) });

I don't understand how local variables inside the Promise function can maintain state. As you can see, when we new up a promise:

let promiseA = new Promise(function (resolve, reject) {
   resolve(1);
})
.then(result => console.log(result * 2),reason => { console.log(reason) });

after partA call is done, the first function Promise(fn) call has been finished , then promiseA.then() is called, note that a new Promise instance is created, i.e the Promise fucntion call function Promise(fn) is called again, so my understanding is that those local variable state and value are re-created on the stack, so how can they be used again by the new promise instance to get the state and value in the second function call?

P.S someone said it is about closure, but I don't see any closure here, isn't that closure is something like:

function foo() {
  const secret = Math.trunc(Math.random() * 100)
  return function inner() {
    console.log(`The secret number is ${secret}.`)
  }
}

but in the 'Promise' function, it doesn't return any function to the newly created promise instance

lch
  • 125
  • 7
  • 1
    Calling `new Promise()` creates a closure around all those inner functions. – Pointy Aug 08 '23 at 12:25
  • It does not maintain state across the two `Promise()` calls. There are indeed two separate states for the two separate promises. However, state is shared amongst all the functions defined in each respective `Promise` call, that is, `fulfill`/`reject`/`resolve`/`handle`/`done`/`then`. – Bergi Aug 08 '23 at 12:38
  • @Bergi sorry, why state is shared amongst all the functions defined in each respective `Promise` call? for example, the `Promise` set `state = FULFILLED` , how does the second `Promise` call read the previous "FULFILLED" `state?` – lch Aug 08 '23 at 14:12
  • @Pointy sorry I don't see closure here, I edited the post – lch Aug 08 '23 at 14:15
  • The closure is formed by the construction of an instance via the Promise constructor. Because those inner functions are lexically scoped inside the constructor, they can "see" the local variables, and so long as there are live references to functions that can call the other local functions, the scope created when the constructor was called will remain available. All JavaScript function calls potentially create a closure that remains available after the function exits. – Pointy Aug 08 '23 at 14:20
  • @lch Again, the second `Promise()` call does **not** read the `state` defined in the first `Promise()` call, it's two separate variables. It is the `.then(…)` and `.done(…)` invocations that read the `state` from the scope in which they were defined. – Bergi Aug 08 '23 at 17:02
  • "*the 'Promise' function […] doesn't return any function*" - it doesn't have to `return` the function itself. It returns an object (`this`) containing the functions (`done` and `then`) which form the closure(s). – Bergi Aug 08 '23 at 17:04

0 Answers0