promise原理

152 阅读12分钟

手写Promise


源码:

type State = "pending" | "resolved" | "rejected";

// 构造函数的回调
// new Promise(Executor)
// new Promise((resolve, reject) => {})
type Executor = (resolve: Function, reject: Function) => any;

// p.then(ThenCB, ThenCB)
type ThenCB = (res: any) => any;

// then 方法每执行一次,就会创建一个 Item
// 每一个item, 就对应一个异步任务, then的回调就在异步任务中执行
type Item = {
  onResolved: ThenCB; // then的回调: .then(成功函数)
  onRejected: ThenCB; // then的回调: .then(, 失败函数)
  nextPromise: {
    resolve: Function;
    reject: Function;
  };
};

export default class MyPromise {
  _state: State;
  _value: any;
  items: Item[]; // 存储所有 then 方法的回调

  constructor(executor: Executor) {
    this._state = "pending";
    this._value = undefined;
    this.items = [];

    try {
      executor(this.resolve.bind(this), this.reject.bind(this));
    } catch (err) {
      this.reject(err);
    }
  }

  // ------------------------------
  // 核心:改变状态
  // ------------------------------

  // executor(this._resolve, this._reject)
  // new Promise((resolve, reject) => {})
  private resolve(value?: any) {
    // 状态吸收只在resolve时发生, reject不发生
    if (islikePromise(value)) {
      pushToTaskQueue(() => value.then(this.resolve, this.reject));
      return;
    }

    this.changeState("resolved", value);
  }

  // executor(this._resolve, this._reject)
  // new Promise((resolve, reject) => {})
  private reject(value?: any) {
    this.changeState("rejected", value);
  }

  private changeState(state: State, value: any) {
    // 状态更改后就不能变了
    if (this._state !== "pending") {
      return;
    }

    this._state = state;
    this._value = value;
    this.runAllItems();
  }

  // ------------------------------
  // 执行 then 队列
  // ------------------------------

  /**
   * 极简一句话总结:
   * 执行 then 回调 → 没回调就透传 → 有回调就执行 → 返回值是 Promise 就跟着它,不是就直接成功
   *
   * 最精简专业版总结:
   * 1.根据当前状态选择成功 / 失败回调
   * 2.如果无回调则状态透传给下一个 Promise
   * 3.如果有回调则执行并获取返回值 x
   * 4.如果 x 为 Promise 则状态跟随,否则直接决议成功
   *
   * 谁在调用函数 task:
   * pushToTaskQueue(() => task(item))
   */
  task(item: Item) {
    const value = this._value;

    const { onResolved, onRejected, nextPromise } = item;
    const state = this._state;
    const thenCB = state === "resolved" ? onResolved : onRejected;

    // 透传
    if (!thenCB) {
      state === "resolved"
        ? nextPromise.resolve(value)
        : nextPromise.reject(value);
      return;
    }

    const x = thenCB(value);

    if (islikePromise(x)) {
      pushToTaskQueue(() => x.then(nextPromise.resolve, nextPromise.reject));
      return;
    }

    nextPromise.resolve(x);
  }

  /**
   * 每一个 Item 都会产生一个异步任务
   *
   * 什么时候执行:
   * 情况1: resolve, reject 执行时触发
   * 情况2: then 方法执行时发现promise对象状态已经改变
   *        Promis.resolve().then(() => alert(1))
   * 注意:
   * 异步任务产生后记得将 item 从 list 中删除, 防止反复执行
   * const p = Promise.resolve()
   * p.then(() => {console.log(1)})
   * p.then(() => {console.log(2)})
   * then ---生---> item ---生--> 异步任务
   */
  private runAllItems() {
    if (this._state === "pending") {
      return;
    }

    while (this.items.length) {
      const item = this.items.shift();

      pushToTaskQueue(() => {
        try {
          this.task(item);
        } catch (error) {
          item.nextPromise.reject(error);
        }
      });
    }
  }

  // 谁在调用函数 addItem: then 方法
  addItem(
    onResolved: ThenCB,
    onRejected: ThenCB,
    nextPromise: Item["nextPromise"],
  ) {
    this.items.push({
      onResolved,
      onRejected,
      nextPromise,
    });
  }

  // ------------------------------
  // 实例方法
  // ------------------------------

  then(onResolved?: ThenCB, onRejected?: ThenCB) {
    return new MyPromise((resolve, reject) => {
      const nextPromise = { resolve, reject };
      this.addItem(onResolved, onRejected, nextPromise);
      // 如果promise的状态已经确定, 就立即执行异步任务
      if (this._state !== "pending") this.runAllItems();
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(callback: Function) {
    return this.then(
      (res) => {
        callback();
        return res;
      },
      (err) => {
        callback();
        throw err;
      },
    );
  }

  // ------------------------------
  // 静态方法
  // ------------------------------

  // 状态吸收
  // const p = Promise.reject("我失败了")
  //
  // Promise.resolve(p).catch(err => {
  //   console.log(err) // 👈 输出:我失败了
  // })
  static resolve(value?: any) {
    if (islikePromise(value)) {
      return value;
    }
    return new MyPromise((resolve) => resolve(value));
  }

  // const p = Promise.resolve("我成功了")
  //
  // Promise.reject(p).catch(err => {
  //   console.log(err) // 👈 输出:整个 p 对象!
  // })
  static reject(reason?: any) {
    return new MyPromise((_, reject) => reject(reason));
  }

  static all(promises: MyPromise[]) {
    return new MyPromise((resolve, reject) => {
      const values = [];
      let count = 0;

      const add = (i, v) => {
        values[i] = v;
        count++;
        if (count >= promises.length) resolve(values);
      };

      promises.forEach((p, i) => {
        MyPromise.resolve(p).then(
          (res) => add(i, res),
          (rej) => reject(rej),
        );
        // 其实可以写成下面这样, 但p就必须是promise对象,不然会出错
        // p.then(
        //   res => add(i, res),
        //   rej => reject(rej)
        // )
      });
    });
  }

  static race(promises: MyPromise[]) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((p) => {
        MyPromise.resolve(p).then(resolve as ThenCB, reject as ThenCB);
        // 简化版:
        // p.then(resolve as ThenCB, reject as ThenCB);
      });
    });
  }
}

function isNodeEnv() {
  if (globalThis.process && globalThis.process.nextTick) {
    return true;
  }
  return false;
}

export function pushToTaskQueue(callback) {
  // node 环境用 nextTick
  if (isNodeEnv()) {
    globalThis.process.nextTick(callback);
    return;
  }
  // 浏览器环境且支持 MutationObserver
  if (MutationObserver) {
    const ob = new MutationObserver(callback);
    const div = document.createElement("div");
    ob.observe(div, { childList: true }); // 监听div, 发生变化就执行cb
    div.innerHTML = "1";
    return;
  }

  setTimeout(callback);
}

function isFn(v: any) {
  return typeof v === "function";
}

function isObj(v: any) {
  return typeof v === "object" && v !== null;
}

//
function islikePromise(p: any) {
  if ((isObj(p) || isFn(p)) && p.then && isFn(p.then)) {
    return true;
  }
  return false;
}

手写工具函数


🩸实现微队列

  • node 环境使用 process.nextTick
  • 浏览器环境使用 MutationObserver
function isNodeEnv() {
  if (process && process.nextTick) {
    return true
  }
  return false
}

export function pushToTaskQueue(callback) {
  // node 环境用 nextTick
  if (isNodeEnv()) {
    globalThis.process.nextTick(callback);
    return;
  }
  // 浏览器环境且支持 MutationObserver
  if (MutationObserver) {
    const ob = new MutationObserver(callback);
    const div = document.createElement("div");
    ob.observe(div, { childList: true }); // 监听div, 发生变化就执行cb
    div.innerHTML = "1";
    return;
  }

  setTimeout(callback);
}

🩸 实现promiseLike

  • 判断条件
    • 是一个对象或函数
    • 有then方法

function isFn(v: any) {
  return typeof v  === 'function'
}

function isObj(v:any) {
  return typeof v === 'object' && v !== null
}

function likePromise(p: any) {
  if (
    (isObj(p) || isFn(p)) && p.then && isFn(p.then)
  ) {
    return true
  }
  return false
}

🩸 实现Promise.all


  Promise.all = function (arr) {
    return new Promise((resolve, reject) => {
      const values = []
      let count = 0

      const add = (i, v) => {
        values[i] = v
        count++
        if (count === promises.length) resolve(values)
      }

      arr.forEach((p, i) => {
        // 其实可以写成下面这样, 但p就必须是promise对象,不然会出错
        // p.then(
        //   res => add(i, res),
        //   rej => reject(rej)
        // )
        Promise.resolve(p).then(
          res => add(i, res),
          err => reject(err)
        )
      })
    })
  }

🩸 实现catch

catch(onRejected) {
    return this.then(null, onRejected)
}

🩸 实现finally


  finally(callback: Function) {
    return this.then(
      res => {
        callback() // promise规范: callback不传值
        return res // 保留状态一致
      },
      err => {
        callback()
        throw err// 保留状态一致
      }
    )
  }

🩸 实现Promise.resolve

  // 状态吸收
  // const p = Promise.reject("我失败了")
  //
  // Promise.resolve(p).catch(err => {
  //   console.log(err) // 👈 输出:我失败了
  // })
  static resolve(value) {
    if (islikePromise(value)) {
      return value;
    }
    return new MyPromise((resolve) => resolve(value));
  }

🩸 实现Promise.reject


  static reject(reason?) {
    return new MyPromise((_, reject) => reject(reason))
  }

async await


🩸 return

情况 1:async 函数里啥也不 return

async function fn1() {
    console.log(111)
}

等于:

function fn1() {
  return new Promise(resolve => {
      console.log(111)
      resolve(undefind)
  })
}

情况 2:async 函数里 return 一个值

async function fn1() {
  return 123
}

等于:

function fn1() {
  return new Promise(resolve => resolve(123))
}

情况 3:async 函数里 return 一个 Promise

触发状态吸收

const p1 = Promise.resolve(1)

// 生成了新的promise对象
async function fn() {
  return p1
}

const p2 = fn()

// p1 不等于 p2, 说明生成了新的promise对象
console.log(p1 === p2) // false

等于:

const p1 = Promise.resolve(1)

// 生成了新的promise对象
function fn() {
  return new Promise(resolve => resolve(p1))
}

const p2 = fn()

console.log(p1 === p2) // false

不能这样写:

const p1 = Promise.resolve(1)

function fn() {
  return Promise.resolve(p1) // 相当于: return p1
}

const p2 = fn()

console.log(p1 === p2) // true

为什么不能写成 Promise.resolve(xxx)

  • async 函数 一定会创建新 Promise
  • 状态吸收时
  • Promise.resolve(p1) === p1, 不会创建新 Promise
  • 详情去看 Promise.resolve源码
async function fn() {
  return p1
}

// 终极一句话总结:
// async 函数的 return,永远等价于:new Promise(resolve => resolve(返回值))
// 绝对不等价于:Promise.resolve(返回值)
// 因为:
// `new Promise` → 一定生成新对象
// `Promise.resolve` → 可能直接返回原来的对象(状态吸收时)

🩸throw error

async function fn1() {
  throw 'err info ...'
}

翻译

  • 写法1, 写法2, 都可以
  • 因为reject没有状态吸收
  • 详情去看Promise.reject源码
// 写法1
function fn1() {
  return Promise.reject('err info ...')
}
// 写法2
function fn1() {
    return new Promise((_, reject) => reject('err info ...'))
}

🩸 async中的状态吸收

// return 了一个promise对象
async function fn1() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(123)
    }, 1000)
  })
}

等于:

// resolve 了一个promise对象
function fn1() {
  const p = new Promise((resolve) => {
    setTimeout(() => {
      resolve(123)
    }, 1000)
  })
  
  return new Promise(resolve => resolve(p)) 
}

🩸 await

案例: C级

async function m(){
  const n = await 1;
  console.log(n);
  // return undefind
}

m();
console.log(2);

翻译:

function m(){
  return new Promise(resolve => {
      Promise.resolve(1).then(n =>{
          console.log(n)
          resolve(undefind)
      })  
  })
}

m();
console.log(2);

// 答案: 2,1

极简:

const n = await 1;
console.log(n);

// 等于: 
Promise.resolve(1).then(n => {
	console.log(n); // 1
})

案例: B级

async function async1() {
  console.log(1);
  const res = await async2();
  console.log(res);
}

async function async2() {
  return 2; // return 相当于 resolve
}

async1();
Promise.resolve().then(() => console.log(3));
// 答案: 1,2,3

案例: A级

和上面区别: 多了个await

async function async1() {
  console.log(1);
  const res = await async2();
  console.log(res);
}

async function async2() {
  return await 2; // 和上一个例子区别: 多了个await
}

async1();
Promise.resolve().then(() => console.log(3));

答案:

// 答案: 1,3,2

// 1
// r-2, 2
// 3

翻译 return await 1

// fn1 === fn2 === fn3 === fn4 === fn5
async function fn1() {
  return await 1
}
// 相当于
async function fn2() {
  return await Promise.resolve(1)
}
// 相当于
async function fn3() {
  const res = await Promise.resolve(1)
  return res
}
// 相当于
function fn4() {
  return new Promise(resolve => {
    Promise.resolve(1).then(res => resolve(res))
  })
}

解析:

// return 相当于 resolve
async function async1() {
  console.log(1);
  // pending状态, 不会立刻进入微队列
  P<pending>.then(res => console.log(res))
}

下面代码, fn1 和 fn2 的区别

  • fn1 执行, resolve 立刻执行
  • fn2 执行, resolve 被推到微队列执行
  • 这就是为什么 p2 的状态为 pending
// 返回的`promise`状态为:success
async function fn1() {
  return 666;
}

// 返回的`promise`状态为:pending
// 只要函数里面有await, 那么返回的`promise`状态必为`pengding`
async function fn2() {
  return await 666;
}


async function fn11() {
  const res = await fn1();
  console.log(res);
}

async function fn22() {
  const res = await fn2();
  console.log(res);
}


// 翻译:
function fn11() {
  P1<666>.then(res => console.log(res)) // 立刻进入微队列
}

function fn22() {
  P2<pending>.then(res => console.log(res)) // 等待状态确定再进入微队列
}

案例: S级

  • 注意 setTimeout 前面有一个 await
async function async1() {
  console.log(1)
  await async2()
  console.log(2)
}

async function async2() {
  await setTimeout(() => {
    Promise.resolve().then(() => console.log(3))
    console.log(4)
  })
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6)
  })
}

async1()
console.log(7)
async3()

答案:

// 答案: const res = [1, 7, 6, 2, 4, 3]

// 1, 7

// r-2, 2
// 6

// 4

案例: S级

  • 注意 setTimeout 前面没有 await
async function async1() {
  console.log(1)
  await async2()
  console.log(2)
}
// 和上面例子唯一的区别: setTimeout 前面没有await
async function async2() {
  setTimeout(() => {
    Promise.resolve().then(() => console.log(3))
    console.log(4)
  })
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6)
  })
}

async1()
console.log(7)
async3()

答案:

// 答案: const res = [1, 7, 2, 6, 4, 3]

// 1, 7

// 2
// 6

// 4

案例: SSS级

  • 考点和上面例题一样, 没什么新的考点
  • 可以忽略不看: 出这种题的都是sb
  • 看不看看心情
  • 区别
    • 代码很乱
    • 废内存, 需要拿一张纸记录
async function async1() {
  console.log(1)
  await async2()
  console.log(2)
}

async function async2() {
  await (async () => {
      await (() => {
        console.log(3)
      })()
      console.log(4)
  })()
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6)
  })
}

async1()
console.log(7)
async3()

整理代码

  • 规律
    • 只要函数里面有await,
    • 那么返回的promise状态必为pengding
async function async1() {
  console.log(1);
  await async2();
  console.log(2);
}

function fn2() {
  console.log(3);
}

// 只要里面有await, 返回的promise状态必为pengding
async function fn1() {
  await fn2();
  console.log(4);
}

async function async2() {
  await fn1();
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6);
  });
}

async1();
console.log(7);
async3();

// 答案 const res = [1, 3, 7, 4, 6, 2]

// 1, 3, 7

// 4, r-2, 2
// 6

案例: SSS级

  • 考点和上面例题一样, 没什么新的考点
  • 可以忽略不看: 出这种题的都是sb
  • 看不看看心情
  • 区别
    • 代码很乱
    • 废内存, 需要拿一张纸记录
async function async1() {
  console.log(1)
  await async2()
  console.log(2)
}

async function async2() {
  await (async () => {
    Promise.resolve().then(() => console.log(3))
    console.log(4)
  })()
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6)
  })
}

async1()
console.log(7)
async3()

整理:

async function async1() {
  console.log(1);
  await async2();
  console.log(2);
}

async function async2() {
  async function fn() {
    await Promise.resolve().then(() => console.log(3));
    console.log(4);
  }

  await fn();
}

async function async3() {
  Promise.resolve().then(() => {
    console.log(6);
  });
}

async1();
console.log(7);
async3();



// 答案 const res = [1, 7,3,6,4,2]

// 1, 7
// 3, 4, r-2, 2
// 6

状态吸收


🩸 状态吸收的场景

// 状态吸收1
const p6 = Promise.resolve("p6-p6-p6");
const p7 = Promise.resolve(p6);
p7.then((res) => console.log(res));

// // 状态吸收2
const p3 = Promise.reject("err msg p3");
const p4 = Promise.resolve().then(() => p3);
p4.catch((err) => console.log(err));

// // 状态吸收3
const p1 = Promise.reject("err msg ...");
const p2 = new Promise((res) => res(p1));
p2.catch((err) => console.log(err));

🩸 第一题

const p1 = new Promise(resolve => resolve(1))
const p2 = new Promise(resolve => resolve(p1))

console.log(p1) 
console.log(p2) 

答案

console.log(p1) // Promise { 1 }
console.log(p2) // Promise { <pending> }

状态吸收对应源码:

private resolve(value?: any) {
	// 状态吸收只在resolve时发生, reject不发生
	if (islikePromise(value)) {
	  pushToTaskQueue(() => value.then(this.resolve, this.reject));
	  return;
	}
	
	this.changeState("resolved", value);
}

🩸 第二题

async function fn1() {
  console.log(1)
  await fn2()
  console.log("AAA")
}

function fn2() {
  return Promise.resolve(2)
}

fn1()

Promise.resolve()
  .then(() => console.log(3))
  .then(() => console.log(4))
  .then(() => console.log(5))

翻译

async function fn1() {
  console.log(1)
  fn2().then(() => console.log("AAA"))
}

function fn2() {
  return Promise.resolve(2)
}

fn1()

Promise.resolve()
  .then(() => console.log(3))
  .then(() => console.log(4))
  .then(() => console.log(5))

答案分析

// 1
// AAA
// 3, 4, 5

// 答案: 1, 'AAA', 3, 4, 5
// 执行: fn2().then(() => console.log("AAA"))
// 添加微任务: () => console.log("AAA")
[
    () => console.log("AAA")
]

// 执行: Promise.resolve().then(() => console.log(3))
// 添加微任务: () => console.log(3)
[
    () => console.log("AAA"),
    () => console.log(3)
]

// 执行 () => console.log("AAA") 没有产生新的微任务
// 执行 () => console.log(3) 
// 添加微任务 () => console.log(4)
[
    () => console.log(4)
]

//执行 () => console.log(4)
//添加微任务 () => console.log(5)
[
    () => console.log(5)
]

🩸 第三题

async function fn1() {
  console.log(1)
  await fn2()
  console.log("AAA")
}

// 与第二题不同的地方fn2: 多了一个 async
// 在 async 函数中, return 一个promise对象, 就相当于resolve一个promise对象
async function fn2() {
  return Promise.resolve(2)
}

fn1()

Promise.resolve()
  .then(() => console.log(3))
  .then(() => console.log(4))
  .then(() => console.log(5))

翻译


async function fn1() {
  console.log(1)
  fn2().then(() => console.log('AAA'))
}

function fn2() {
  return new Promise((resolve) => {
    const p1 = Promise.resolve(2)
    resolve(p1)
  })
}

fn1()

Promise.resolve()
  .then(() => console.log(3))
  .then(() => console.log(4))
  .then(() => console.log(5))

答案分析

// 1, 
// then(r-AAA), r-AAA, AAA
// 3, 4, 5

// 打印结果为: 1, 3, 4, 'AAA', 5
// 同步任务
[
    console.log(1)
]
// 微任务
[
    // 谁生成的该微任务: 
    // resolve(p1)
    () => p1.then(resolve) 
    // 谁生成的该微任务: 
    // Promise.resolve().then(()=>console.log(3))
    () => console.log(3)
    // 谁生成的该微任务: 
    // () => p1.then(resolve) 
    () => resolve()
    // 谁生成的该微任务: 
    // () => console.log(3)
    () => console.log(4)
    // 谁生成的该微任务: 
    // () => resolve()
    () => console.log("AAA")
    // 谁生成的该微任务: 
    // () => console.log(4)
    () => console.log(5)    
]

源码

private resolve(value?: any) {
	// 状态吸收只在resolve时发生, reject不发生
	if (islikePromise(value)) {
	  pushToTaskQueue(() => value.then(this.resolve, this.reject));
	  return;
	}
	
	this.changeState("resolved", value);
}

🩸 第四题

const p1 = new Promise((resolve) => resolve(1))
const p2 = new Promise((resolve) => resolve(p1))

p2
  .then(() => console.log(1))
  .then(() => console.log(2))
  .then(() => console.log(3))

p1
  .then(() => console.log(4))
  .then(() => console.log(5))
  .then(() => console.log(6))

答案

// then(r-1), r-1, 1, 2, 3
// 4, 5, 6

// 答案: 4, 5, 1, 6, 2, 3
// 微队列
[
  () => p1.then(resolve),
  () => console.log(4),
  () => resolve(),// 添加者:() => p1.then(resolve),
  () => console.log(5),//添加者:() => console.log(4) 
  () => console.log(1),//添加者:() => resolve()
  () => console.log(6),//添加者:() => console.log(5) 
  () => console.log(2),//添加者:() => console.log(1) 
  () => console.log(3),//添加者:() => console.log(2) 
]

🩸 第五题

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))

答案

// 0, then(r-4), r-4, 4, 
// 1, 2, 3, 5

// 答案: 0,1,2,3,4,5
const microTask = [
  () => {
    console.log(0)
    return Promise.resolve(4) // return p4
  },
  () => console.log(1), 
  () => p4.then(resolve), 
  () => console.log(2),
  () => resolve(4),
  () => console.log(3),
  (res) => console.log(res), // res=4
  () => console.log(5),
]

对应源码

const x = thenCB(value);

if (islikePromise(x)) {
  pushToTaskQueue(() => x.then(nextPromise.resolve, nextPromise.reject));
  return;
}

其他面试题


🩸 交替执行

Promise.resolve()
  .then(() => console.log(1))
  .then(() => console.log(2))
  .then(() => console.log(3));

Promise.resolve()
  .then(() => console.log(10))
  .then(() => console.log(20))
  .then(() => console.log(30));

Promise.resolve()
  .then(() => console.log(100))
  .then(() => console.log(200))
  .then(() => console.log(300));

答案

// 1,2,3
// 10, 20, 30
// 100, 200, 300

// 答案: 
//  1
//  10
//  100
//  2
//  20
//  200
//  3
//  30
//  300

🩸 catch error

案例1

    Promise.resolve()
    .then(res => {
        console.log('---------- 111')	// √
        throw new Error()
    })
    .catch(err => {
        console.log('---------- 222')	// √
    })
    .then(res => {
        console.log('---------- 333')	// √
    })

案例2

    Promise.resolve()
    .then(res => {
        console.log('---------- 111')	// √
        throw new Error()
    })
    .catch(err => {
        console.log('---------- 222')	// √
    })
    .catch(res => {
        console.log('---------- 333')
    })

🩸 事件循环

setTimeout(() => {
  console.log(1)
})

const p = new Promise(resolve => {
  console.log(2)
  resolve(3) 
  Promise.resolve(4).then(console.log)
  console.log(5)
}).then(console.log)
console.log(6)

解析

const p = new Promise(resolve => {
  console.log(2)
  resolve(3) // 注意:此时 Promise 的 then 方法尚未注册
  Promise.resolve(4).then(console.log)
  console.log(5)
}).then(console.log)

答案

// 2,5,6 
// 4
// 3
// 1

// 答案: [2, 5, 6, 4, 3, 1]
const res = [2, 5, 6, 4, 3, 1]

const macroTask = [
  () => console.log(1),
]

const microTask = [
  () => console.log(4),
  () => console.log(3),
]

🩸 构造函数

new Promise((resolve, reject) => {
  reject(1)
  console.log(2)
  resolve(3)
  console.log(4)
})
  .then(res => console.log(res))
  .catch(err => console.log(err))

try {
  new Promise((resolve, reject) => {
    throw 6
  })
  .then(console.log)
  .catch(err => console.log(8))
} catch (error) {
  console.log(error)
}

答案

// 2, 4,
// r-1, 1
// r-8, 8

// 答案
const res = [2, 4, 1, 8]

🩸 微任务

const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
})

promise.then(() => {
    console.log(3);
})

console.log(4);
// 答案: 1,2,4,3

// 1, 2, 4
// 3

🩸 宏任务+微任务

const promise = new Promise((resolve, reject) => {
  console.log(1); 
  setTimeout(()=>{
    console.log(2)
    resolve(null); 
    console.log(3);
  })
})

promise.then(() => {
  console.log(4);
})

console.log(5);

// 答案: 1,5,2,3,4

🩸 透传

例1

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000)
})
const promise2 = promise1.catch(() => {
  return 2;
})

console.log('promise1', promise1) 
console.log('promise2', promise2) 

setTimeout(() => {
  console.log('promise1', promise1) 
  console.log('promise2', promise2) 
}, 2000)

翻译

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000)
})

const promise2 = promise1.then(
  null,
  () => 2
)

console.log('promise1', promise1) 
console.log('promise2', promise2) 

setTimeout(() => {
  console.log('promise1', promise1) 
  console.log('promise2', promise2) 
}, 2000)

// 答案:
// promise1 Promise { <pending> }
// promise2 Promise { <pending> }
// promise1 Promise { 1 }
// promise2 Promise { 1 }

例2

    Promise.resolve()
    .then(res => {
        console.log('---------- 111') // √
    })
    .catch(err => {
        console.log('---------- 222')
    })
    .then(res => {
        console.log('---------- 333')	// √
    })

解析

    Promise.resolve()
    .then(res => console.log('---------- 111'))// √
    .then(null, err => console.log('---------- 222'))
    .then(res => console.log('---------- 333'))// √

例3

const p1 = Promise.reject()
  .then(() => console.log(1))
  .then(() => console.log(2))
  .catch(() => console.log(3));

const p2 = Promise.resolve()
  .then(() => console.log(4))
  .then(() => console.log(5));

答案


// r, r, 3
// 4, 5

// 答案: 4, 5, 3

解析

// 不会看源码
[
  reject1,
  console.log(4),
  reject2
  console.log(5)
  console.log(3)
]