Post the topic first

Public number: hand touch hand front step
Promise.resolve().then(() = > {
    console.log(0);
    return Promise.resolve(4);
}).then((res) = > {
    console.log(res)
})

Promise.resolve().then(() = > {
    console.log(1);
}).then(() = > {
    console.log(2);
}).then(() = > {
    console.log(3);
}).then(() = > {
    console.log(5);
}).then(() = >{
    console.log(6);
})
Copy the code

After reading this question, what is your answer?

0 -> 2 -> 3 -> 4 -> 5 -> 6

So, did you do it right?

Is not like me entangled for wool 4 ran in the back of 3 😂

Here is my own understanding:

First of all, we know that microtasks are performed alternately

Here is an example:

So the first time I did it, the answer was: 0-> 1 -> 4 -> 2 -> 3 -> 5 -> 6

But the actual output of the fourth round missed twice, running behind the third

So if I change output 4, what does it say?

Amazing🤩, the result is 0->1->4->2->3->5->6

OK ~, with such doubts, I seem to understand a little, and went to look at the Promsie source code I learned before, and finally came to the following conclusions:

If the return value is a nested Promise object, the current THEN method must evaluate its final value and pass it back to the next THEN callback. Check if the value is a Promise object, so two more microtasks.)

Attached handwritten Promise source code:

const PENDING = 'pending'; / / wait for
const FULFILLED = 'fulfilled'; / / success
const REJECTED = 'rejected'; / / fail

class MyPromise {
  constructor (executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e); }}/ / promsie state
  status = PENDING;
  // Value after success
  value = undefined;
  // Cause of failure
  reason = undefined;
  // Successful callback
  successCallback = [];
  // Failed callback
  failCallback = [];

  resolve = value= > {
    // If the state is not waiting to prevent the program from executing down
    if (this.status ! == PENDING)return;
    // Change the status to success
    this.status = FULFILLED;
    // Save the value after success
    this.value = value;
    // Determine if the successful callback exists
    // this.successCallback && this.successCallback(this.value);
    while(this.successCallback.length) this.successCallback.shift()()
  }
  reject = reason= > {
    // If the state is not waiting to prevent the program from executing down
    if (this.status ! == PENDING)return;
    // Change the status to failed
    this.status = REJECTED;
    // Cause of save failure
    this.reason = reason;
    // Determine if the failed callback exists
    // this.failCallback && this.failCallback(this.reason);
    while(this.failCallback.length) this.failCallback.shift()()
  }
  then (successCallback, failCallback) {
    // Parameters are optional
    successCallback = successCallback ? successCallback : value= > value;
    // Parameters are optional
    failCallback = failCallback ? failCallback: reason= > { throw reason };
    let promsie2 = new MyPromise((resolve, reject) = > {
      // Determine the status
      if (this.status === FULFILLED) {
        setTimeout(() = > {
          try {
            let x = successCallback(this.value);
            // Determine whether x is a normal value or a promise object
            // Call resolve directly if it is a normal value
            // If it is a Promise object, look at the results returned by promsie
            // Call resolve or reject based on the result returned by the Promise object
            resolvePromise(promsie2, x, resolve, reject)
          }catch(e) { reject(e); }},0)}else if (this.status === REJECTED) {
        setTimeout(() = > {
          try {
            let x = failCallback(this.reason);
            // Determine whether x is a normal value or a promise object
            // Call resolve directly if it is a normal value
            // If it is a Promise object, look at the results returned by promsie
            // Call resolve or reject based on the result returned by the Promise object
            resolvePromise(promsie2, x, resolve, reject)
          }catch(e) { reject(e); }},0)}else {
        / / wait for
        // Store the success and failure callbacks
        this.successCallback.push(() = > {
          setTimeout(() = > {
            try {
              let x = successCallback(this.value);
              // Determine whether x is a normal value or a promise object
              // Call resolve directly if it is a normal value
              // If it is a Promise object, look at the results returned by promsie
              // Call resolve or reject based on the result returned by the Promise object
              resolvePromise(promsie2, x, resolve, reject)
            }catch(e) { reject(e); }},0)});this.failCallback.push(() = > {
          setTimeout(() = > {
            try {
              let x = failCallback(this.reason);
              // Determine whether x is a normal value or a promise object
              // Call resolve directly if it is a normal value
              // If it is a Promise object, look at the results returned by promsie
              // Call resolve or reject based on the result returned by the Promise object
              resolvePromise(promsie2, x, resolve, reject)
            }catch(e) { reject(e); }},0)}); }});return promsie2;
  }
  finally (callback) {
    return this.then(value= > {
      return MyPromise.resolve(callback()).then(() = > value);
    }, reason= > {
      return MyPromise.resolve(callback()).then(() = > { throw reason })
    })
  }
  catch (failCallback) {
    return this.then(undefined, failCallback)
  }
  static all (array) {
    let result = [];
    let index = 0;
    return new MyPromise((resolve, reject) = > {
      function addData (key, value) {
        result[key] = value;
        index++;
        if(index === array.length) { resolve(result); }}for (let i = 0; i < array.length; i++) {
        let current = array[i];
        if (current instanceof MyPromise) {
          / / promise object
          current.then(value= > addData(i, value), reason= > reject(reason))
        }else {
          / / common valuesaddData(i, array[i]); }}})}static resolve (value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve= >resolve(value)); }}function resolvePromise (promsie2, x, resolve, reject) {
  if (promsie2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof MyPromise) {
    / / promise object
    // x.then(value => resolve(value), reason => reject(reason));
    x.then(resolve, reject);
  } else {
    / / common valuesresolve(x); }}module.exports = MyPromie;
Copy the code

A Promsie interview question that Kept me up