ECMAScript 6 - 通过输出题理解「Promise」

23 篇文章 0 订阅

1 题目(1)

1.1 题目背景:分享@洛千陨 珍藏题

const p1 = () => (new Promise((resolve, reject) => {
 console.log(1);
 let p2 = new Promise((resolve, reject) => {
  console.log(2);
  const timeOut1 = setTimeout(() => {
   console.log(3);
   resolve(4);
  }, 0)
  resolve(5);
 });
 resolve(6);
 p2.then((arg) => {
  console.log(arg);
 });

}));
const timeOut2 = setTimeout(() => {
 console.log(8);
 const p3 = new Promise(reject => {
  reject(9);
 }).then(res => {
  console.log(res)
 })
}, 0)


p1().then((arg) => {
 console.log(arg);
});
console.log(10);
输出结果:1 2 10 5 6 8 9 3

输出结果分析

  • 思路:同步->异步
  • 疑问:为什么先5后6?

宏任务队列:8 9 3 4
(8-9这一块都是属于setTimeout里面的,下一轮 Event Loop再执行;resolve(5)后不输出4)

微任务队列:5 6
(为什么先5后6, 因为在p2定义的时候会执行promise内部的代码, resolve(5)时有下面p2.then接收就会打印5)

JS主线程-同步代码:1 2 10

注意点

  1. p1是个返回1个promise对象的普通函数需要p1()执行,p1().then接收回调;p2是个promise对象,p2.then接收回调。
  2. Promise 第一个参数是成功时的回调resolve, reject只是变量名。
    const p3 = new Promise(reject => {
    reject(9);
    }).then(res => {
    console.log(res)
    })

1.2 延伸变形一

const p1 = () => (new Promise((resolve, reject) => {
 console.log(1);
 resolve(6);
 let p2 = new Promise((resolve, reject) => {
  console.log(2);
  const timeOut1 = setTimeout(() => {
   console.log(3);
   resolve(4);
  }, 0)
  resolve(5);
 });
 
 p2.then((arg) => {
  console.log(arg, 'p2 then');
 });

}));

p1().then((arg) => {
 console.log(arg,'p1 then');
});
console.log(10);
输出结果:1 2 10 5 6 8 9 3

问题为什么'6'在'5'前面还是先输出'5' ?!!
:这里p1()调用->执行了p2.then,再执行p1.then,所以’5’比’6’先输出
在这里插入图片描述
1.3 延伸变形二

const p1 = () => (new Promise((resolve, reject) => {
    console.log(1);
    resolve(6);
    let p2 = new Promise((resolve, reject) => {
     console.log(2);
     const timeOut1 = setTimeout(() => {
      console.log(3);
      resolve(4);
     }, 0)
     resolve(5);
    });
    p2.then((arg) => {
     console.log(arg);
     return 'hello'
    }).then((value) => {
        console.log(value)
    });
   
   }));
   const timeOut2 = setTimeout(() => {
    console.log(8);
    const p3 = new Promise(reject => {
     reject(9);
    }).then(res => {
     console.log(res)
    })
   }, 0)
   
   
   p1().then((arg) => {
    console.log(arg);
   });
   console.log(10);
输出结果:
1 2 10 5 6 hello 8 9 3

输出结果分析

  • 疑问:为什么’6’比’hello’先打印?
    答:参照源码,promise的then方法里面会返回一个promise。
    ①p2第一个then里的代码推入微任务队列(第一个),p1.then里的代码推入微任务队列(第二个);
    ②现在来执行第一个微任务打印'5',return 'hello’会把p2第二个then里的代码推入微任务队列(第三个);
    ③执行第二个微任务打印'6'
    ④执行第三个微任务打印'hello'
    promise的源码参考我的另一篇博客:Promise高级版 - 通过输出题理解「Promise源码」

2 题目(2)

题目背景:手写题 - 实现一个带并发限制的异步调度器

class Scheduler {
  constructor(max) {
    this.max = max
    this.count = 0 
    this.queue = new Array() 
  }

  async add(promiseCreator) {
    if (this.count >= this.max) {
      await new Promise((resolve, reject) => {
        this.queue.push(resolve)
      })
    }
    this.count++
    const res = await promiseCreator()
    this.count--

    if (this.queue.length) {
      this.queue.shift()()
    }
    console.log('res: ', res)

    return res
  }
}
const timeout = (time) => new Promise(resolve => {
  console.log('100')
  setTimeout(resolve, time)
})

const scheduler = new Scheduler(2)
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => {console.log(order); return 'timeout'})
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
输出结果:
100
100

res: undefined
100
2

res: undefined
100
3

res: undefined
1

res: undefined
4

输出结果分析

  • Part 1:
    (1)addTask1000、addTask500:
    走两次到这儿
    this.count++
    const res = await promiseCreator(); 都输出’100’,先打印2个'100'
    (2)addTask300、addTask400:
    /** 这个new Promise单纯只是为了创建个微任务去等,前面加了await,没有resolve()是不会往下走的 */
    await new Promise((resolve, reject) => {
    this.queue.push(resolve);
    });
  • Part 2:
    (3)500ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
    (4)∵this.queue.shift()()即resolve()是同步代码,
    addTask300走到这儿
    this.count++
    const res = await promiseCreator();
    ∴先打印下一个'100'再return res打印'2'
  • Part 3:
    (5)接下来同理,300ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
    (6)∵this.queue.shift()()即resolve()是同步代码,
    addTask400走到这儿
    this.count++
    const res = await promiseCreator();
    ∴先打印下一个'100'再return res打印'3'
  • Part 4:
    (7)1000ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
    (8)没有下一个’100’了,return res打印'1'
  • Part 5:
    (9)400ms的timeout执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
    (10)没有下一个’100’了,return res打印'4'

在这里插入图片描述

Promise基本概念

可参考我的另外一篇博客:ECMAScript 6 Promise - Promise

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值