• 基础题--promise练习题(1)


    事件循环(event loop)

    事件循环的过程

    1. 一开始的整体代码视为宏任务代码,先在执行栈同步执行
    2. 执行栈中的代码执行过程中产生新的微任务和宏任务,它们分别进入各自的队列
    3. 执行栈为空,检查微任务队列,将微任务按先进先出的顺序一个一个地提取到执行栈中执行
    4. 微任务队列为空时,开始执行宏任务,每当执行完一个宏任务就回去检查微任务队列是否有新的微任务,如果有则去执行微任务,当微任务队列再次为空时,再去执行宏任务,如此循环。

    被放到执行栈中的代码都会以同步代码执行

    异步任务分为宏任务和微任务,同步代码先于异步代码执行,微任务先于宏任务。
    微任务包括:

    1. MutationObserver、
    2. Promise.then()或catch()、
    3. Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、
    4. Node独有的process.nextTick。
    

    宏任务包括:

    1. script(整体代码)
    2. setTimeout
    3. setInterval
    4. I/O
    5. UI交互事件
    6. postMessage
    7. MessageChannel
    8. setImmediate(Node.js 环境)
    

    基础题

    题目1

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

    输出

    'promise1'
    '1' Promise{<pending>}
    

    分析:

    1. 执行同步代码
      • 给promise1赋值
      • 执行console.log('promise1')
      • 执行console.log('1', promise1);,此时promise1没有被resolve或者reject,因此状态还是pending
    2. 因为resolve和reject才是异步函数,但这里并没有调用并使用then赋值,所以异步任务队列均为空

    题目2

    const promise = new Promise((resolve, reject) => {
      console.log(1);
      resolve('success')
      console.log(2);
    });
    promise.then(() => {
      console.log(3);
    });
    console.log(4);
    

    输出:

    1
    2
    4
    3
    

    分析:

    1. 执行执行栈中的同步代码
      • promise赋值,执行Promise中的同步代码,打印1,调用resolve回调函数,因为是异步函数且为微任务所以放入了微任务队列,打印2
      • promise.then给相应的resolve赋值,以箭头函数为值
      • 执行同步代码,打印4
    2. 检查微任务队列,执行resolveconsole.log(3)被放入执行栈执行

    题目3

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

    输出:

    1
    2
    4
    

    分析:同题目2,但是因为promise的resolve函数没有被调用,所以即使赋予了箭头函数也不会执行,于是就不会打印3。
    promise.then只有在被改变了状态之后才会执行。

    题目4

    const promise1 = new Promise((resolve, reject) => {
      console.log('promise1')
      resolve('resolve1')
    })
    const promise2 = promise1.then(res => {
      console.log(res)
    })
    console.log('1', promise1);
    console.log('2', promise2);
    

    分析:

    'promise1'
    '1' Promise{<resolved>: 'resolve1'}
    '2' Promise{<pending>}
    'resolve1'
    

    分析:

    1. 执行同步代码:
      • 给promise1赋值,执行其中的代码,打印“promise1”,调用resolve改变promise1的状态
      • 给promise2赋值,这里“Promise.prototype.then() 方法返回一个新的期约实例”,因为promise2是基于promise1创建的,但在promise1的处理函数被放入执行栈执行之前,promise2的状态仍是pending。
      • promise1的处理函数进入微任务队列
      • 打印1和promise1的状态
      • 打印2和promise2的状态(现在promise1的处理函数尚未执行,所以是pending)
    2. 检查微任务队列,执行promise1的resolve,打印传入的"res",即打印“resolve1”

    改一改代码:

    const promise1 = new Promise((resolve, reject) => {
      console.log('promise1')
      resolve('resolve1')
    })
    console.log('1', promise1);
    const promise2 = promise1.then(res => {
      console.log('ahead', promise2);
      console.log("res",res);
    })
    //promise2.then(res=>console.log("promise2",res),rej=>console.log("err"));
    console.log('1', promise1);
    console.log('2', promise2);
    setTimeout(console.log,0,'2',promise2);
    

    输出:

    promise1
    1 Promise { <state>: "fulfilled", <value>: "resolve1" }
    1 Promise { <state>: "fulfilled", <value>: "resolve1" }
    2 Promise { <state>: "pending" }
    ahead Promise { <state>: "pending" }
    res resolve1
    2 Promise { <state>: "fulfilled", <value>: undefined }
    

    最终的promise2是处于fulfilled状态的

    关于值传递的:

    const promise1 = new Promise((resolve, reject) => {
      console.log('promise1')
      resolve('resolve1')
    })
    const promise2 = promise1.then(res => {
      console.log("res",res);
      return "resolve2";
    })
    promise2.then(res=>console.log("promise2",res),rej=>console.log("err"));
    console.log('1', promise1);
    console.log('2', promise2);
    setTimeout(console.log,0,'2',promise2);
    

    输出:

    promise1
    1 Promise { <state>: "fulfilled", <value>: "resolve1" }
    2 Promise { <state>: "pending" }
    res resolve1
    promise2 resolve2
    2 Promise { <state>: "fulfilled", <value>: "resolve2" }
    

    对比上面两段代码可以发现,当promise1的resolve没有显式返回一个值时,以const promise2 = promise1.then创建的promise2获得的值是undefined。而当上一个期约返回一个值时,该值将被promise2传给相应的处理函数。

    题目5

    const fn = () => (new Promise((resolve, reject) => {
      console.log(1);
      resolve('success')
    }))
    fn().then(res => {
      console.log(res)
    })
    console.log('start')
    

    输出:

    1
    start
    success
    

    分析:
    fn返回的是一个解决期约(fulfilled)。

    题目6

    const fn = () =>
      new Promise((resolve, reject) => {
        console.log(1);
        resolve("success");
      });
    console.log("start");
    fn().then(res => {
      console.log(res);
    });
    

    输出:

    start
    1
    success
    

    分析:同步代码前面的先执行。

    感谢阅读。

    百炼成钢!!!

    参考:

    【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理)
    《JavaScript高级程序设计》(第四版)

  • 相关阅读:
    Ajax
    PS将图标变灰
    圆角
    前端性能优化最佳实践(转)
    jquery $(document).ready() 与window.onload的区别
    js阻止冒泡及jquery阻止事件冒泡示例介绍
    CSS选择器、CSS hack及CSS执行效率
    Github快速入门手册
    Windows 系统下Git安装图解
    史上最全github使用方法:github入门到精通
  • 原文地址:https://www.cnblogs.com/liulangbxc/p/15338720.html
Copyright © 2020-2023  润新知