zoukankan      html  css  js  c++  java
  • 基础题--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高级程序设计》(第四版)

  • 相关阅读:
    Study Plan The Twelfth Day
    Study Plan The Fifteenth Day
    Study Plan The Seventeenth Day
    Study Plan The Tenth Day
    Study Plan The Eighth Day
    Study Plan The Eleventh Day
    Study Plan The Sixteenth Day
    Study Plan The Thirteenth Day
    Study Plan The Fourteenth Day
    Study Plan The Ninth Day
  • 原文地址:https://www.cnblogs.com/liulangbxc/p/15338720.html
Copyright © 2011-2022 走看看