基础题--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高级程序设计》(第四版)

posted @ 2021-09-26 16:23  叶际参差  阅读(208)  评论(0编辑  收藏  举报