Promise真题详解,看完你就是Promise大王


title: Promise真题详解
date: 2022-09-15 21:41:06
tags:

  • Promise
  • es6
    categories:
  • Js

Promise真题详解

解释会涉及到事件循环等知识点,如果这一点薄弱的可以先去了解一下事件循环

第一题

没必要上来就放大招,先来个简单的,这是我之前看文章收藏的一道题

console.log("start");
setTimeout(() => {
    console.log("children2")
    Promise.resolve().then(() => {
        console.log("children3")
    })
}, 0)

new Promise(function(resolve, reject) {
    console.log("children4")
    setTimeout(function() {
        console.log("children5")
        resolve("children6")
    }, 0)
}).then(res => {
    console.log("children7")
    setTimeout(() => {
        console.log(res)
    }, 0)
});

//--结果--
// start
// children4
// children2
// children3
// children5
// children7
// children6
  1. 遇到这种promise题首先想到的就是出题人的需求,promise类型的题都是要执行结果,你只需要一行一行代码的分析就可以
  2. 先执行同步的代码,比如第一行的console.log("start"),所以第一个输出start
  3. 下一行执行到setTimeout,要知道,setTimeout是同步的,但是里面的回调函数是异步任务,并且要放置到宏任务队列,此时宏任务队列有一个等待执行的函数
  4. 接着下一行的new Promise(...),由于其传入的函数是立即执行的,所以第二个输出children4
  5. 下一行又遇到setTimeout,执行,里面的实参回调函数为异步任务,放到宏任务队列中,此时宏任务队列有两个等待执行的函数
  6. 有很多人会去看then,要知道由于new Promise(...)的实例对象此时还是执行中状态pending,then中的第一个回调是不执行的,所以先不考虑then
  7. 同步的任务执行完毕,先看微任务队列有没有待执行的函数,没有。去宏任务执行。第一个,也就是第一个setTimeout(...),so第三个输出children2
  8. 下一行的Promise.resolve()返回的值是成功状态的promise实例对象,并将它后面的.then(..)中的函数放到微任务队列待执行
  9. 第一个宏任务执行完毕就要去微任务队列查看是否有待执行的任务,就是说,每执行完一个宏任务都要去微任务队列看有没有任务,微任务队列清空,宏任务才执行。
  10. 此时微任务队列有一个任务,所以执行;第四个输出children3,微任务队列为空,去执行宏任务队列
  11. 接着第五个输出children5,执行了resolve(...),此时外层的new Promise()改变状态为成功态
  12. 由于外层new Promise(..)实例对象的状态改变,其.then中的第一个成功函数可以执行,并且接受的值为resolve(..)传入的实参。当然这个.then中的函数也是要放到微任务队列中的。
  13. 执行微任务队列中的任务,第六个输出children7,下一行的setTimeout(..)中的函数放到宏任务队列
  14. 查看微任务队列,空;去执行宏任务中的任务。第七个输出children6;那个res值就是上文resolve(...)传入的实参

第一题只是“开胃菜”,当然第一题如果理解的很透彻了,那么后面的题就都是”下酒菜“,这种事件循环类的题最好是画图理解,有两个队列往里面填充任务,这样看起来方面一些

第二题

    new Promise((resolve, reject) => {
        console.log("外部promise");
        resolve();
    }).then(() => {
        console.log("外部第一个then");
        return new Promise((resolve, reject) => {
            console.log("内部promise");
            resolve();
        }).then(() => {
                console.log("内部第一个then");
            }).then(() => {
                console.log("内部第二个then");
            });
    }).then(() => {//注:这里返回的对象是最后一个.then返回的对象, 第一次时状态为‘pending’
        //注:所以第一次这里会缓存起来并不是加入队列
        console.log("外部第二个then");
    });

// --结果--
// 外部promise
// 外部第一个then
// 内部promise
// 内部第一个then
// 内部第二个then
// 外部第二个then
  1. 先执行new Promise(..)中的同步任务,第一个输出外部promise
  2. 遇到resolve(),说明这个promise实例是成功状态,将其后面的第一个.then()放到微任务队列,第二个.then()由于前一个.then()还是正在执行状态,所以里面的函数暂存
  3. 执行微任务队列,第二个输出外部第一个then,触发return后面的new Promise,所以第三个输出内部promise,走到resolve(),这个promise状态改变,其后面的第一个.then()放到微任务队列,第二个.then暂存
  4. 执行微任务队列,第四个输出内部第一个then,而then()中的函数默认return一个新的Promise实例,所以第二个.then()中的函数放到微任务队列。并且执行第五个输出内部第二个then,同时return一个新的Promise实例对象。
  5. 这时候最外层的第一个.then()有return新的Promise,所以第二个.then()放到微任务队列。
  6. 执行微任务队列,所以第六个输出外部第二个then

第三题

    new Promise((resolve, reject) => {
            console.log("外部promise");
            resolve();
        }).then(() => {
            console.log("外部第一个then");
            new Promise((resolve, reject) => {
                    console.log("内部promise");
                    resolve();
                }).then(() => {
                    console.log("内部第一个then");
                }).then(() => {
                    console.log("内部第二个then");
                });
        }).then(() => { 
            console.log("外部第二个then");
        });

// --结果--
// 外部promise
// 外部第一个then
// 内部promise
// 内部第一个then
// 外部第二个then
// 内部第二个then

这一题其实就是第二题修改版

  1. 首先执行new Promise()内的同步任务,第一个输出外部promise,遇到resolve(),new Promise变成成功状态,后面的第一个.then()放到微任务队列,第二个.then()暂存。
  2. 执行微任务队列第二个输出外部第一个then,执行new Promise()中的同步任务,所以第三个输出内部promise,遇到resolve()状态改变,后面的第一个.then()放到微任务队列,后面的.then()暂存。
  3. 此时这个正在执行的.then()return的是undefined,所以外面的最后一个.then(),放到微任务队列。
  4. 执行微任务队列第一个,所以第四个输出内部第一个then,并且return的也是一个undefined,后面的.then()也放到微任务队列
  5. 接着执行下一个微任务队列中的任务,也就是最外层的.then()中的函数,第五个输出外部第二个then
  6. 最后一个微任务,也就是最内层的.then()第六个输出内部第二个then

更多题…

    async function async1() {
        console.log("async1 start")
        await async2();
        //await async2(), 这里的代码相当于new Promise(()=>{async2()})
        //而将 await 后面的全部代码放到.then()中去
        console.log("async1 end")
    };

    async function async2() {
        console.log("async2")
    };

    console.log("script start");

    setTimeout(function() {
        console.log("setTimeout")
    }, 0);

    async1();

    new Promise(function(resolve) {
        console.log("promise1")
        resolve()
    }).then(function() {
        console.log("promise2")
    });

    console.log("script end");


    // script start
    // async1 start
    // async2
    // promise1
    // script end
    // async1 end
    // promise2
    // setTimeout
    console.log("start");
    setTimeout(() => {
        console.log("children2")
        Promise.resolve().then(() => {
            console.log("children3")
        })
    }, 0)

    new Promise(function(resolve, reject) {
        console.log("children4")
        setTimeout(function() {
            console.log("children5")
            resolve("children6")
        }, 0)
    }).then(res => {
        console.log("children7")
        setTimeout(() => {
            console.log(res)
        }, 0)
    });

    // start
    // children4
    // children2
    // children3
    // children5
    // children7
    // children6
    var p = new Promise(resolve => {
        console.log(4);
        resolve(5);
    }).then(resolve => {
        console.log(resolve);
    });

    function func1() {
        console.log(1);
    };

    function fun2() {
        setTimeout(() => {
            console.log(2);
        });
        func1();
        console.log(3);

        new Promise(resolve => {
            resolve();
        }).then(resolve => {
            console.log('新的resolve');
        })

        p.then(resolve => {
            console.log(7);
        }).then(resolve => {
            console.log(6);
        });
    }
    fun2()

    // 4
    // 1
    // 3
    // 5
    // 新的resolve
    // 7
    // 6
    // 2
async function async1() {
        console.log('async1 start');
        const result = await async2();
        console.log(result);
        // 会先执行async2函数, 然后跳出async1, 同时将返回的promise放入微队列
        console.log('async1 end');
    }
    async function async2() {
        console.log('async');
        return "testAwait";
    }
    console.log('script start');
    setTimeout(function() {
        console.log('setTimeout');
    }, 0);
    async1();
    new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
    new Promise(function(resolve) {
        console.log('promise3');
        resolve();
    }).then(function() {
        console.log('promise4');
    });
    console.log('script end');

    // script start
    // async1 start
    // async
    // promise1
    // promise3
    // script end
    // testAwait
    // async1 end
    // promise2
    // promise4
    // setTimeout
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值