0%

Promise 经典面试题

Promise 经典面试题

可复制题目到js在线运行工具看答案

题目一

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Promise.resolve().then(() => {
console.log(0);
return Promise.resolve(4);
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
答案
1
2
3
4
5
6
7
0
1
2
3
4
5
6
解析

待解析

题目二

代码
1
2
3
4
5
6
7
8
9
10
11
12
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
new Promise(function(resolve) {
console.log('promise1');
resolve();
console.log('promise2');
}).then(function() {
console.log('promise then');
});
console.log('script end');

答案

1
2
3
4
5
6
script start
promise1
promise2
script end
promise then
setTimeout

解析

首先 JavaScript 引擎会执行一个宏任务,注意这个宏任务一般是指主干代码本身,也就是目前的同步代码;

执行过程中如果遇到微任务,就把它添加到微任务任务队列中;

宏任务执行完成后,立即执行当前微任务队列中的微任务,直到微任务队列被清空;

微任务执行完成后,开始执行下一个宏任务;

如此循环往复,直到宏任务和微任务被清空。

题目三

代码
1
2
3
4
5
6
7
8
9
10
11
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
})

promise.then(() => {
console.log(3);
})

console.log(4);
答案
1
2
3
4
1
2
4
3
解析

遇到 Promise 之后立即执行,输出 1,2
执行同步代码,输出 4
执行 promise.then() 中的代码,输出 3

题目四

代码
1
2
3
4
5
6
7
8
9
10
11
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});

promise.then((res) => {
console.log('then:', res);
}).catch((err) => {
console.log('catch:', err);
})
答案
1
then: success1
解析

这里考察了 promise 的单向传递的特点,promise 有三种状态:
pending
resolved
rejected
这三种状态的转移只能是 pending -> resolved 或 pending -> rejected。不会出现 resolved -> rejected 或者 pending -> resolved -> rejected 等等,即状态只能从 pending 单向传递,且只能改变一次。
在 promise 中,resolve() 将 promise 的状态变为 resolved成功时调用,resolved 状态在先,先调用异步函数 promise.then((‘success1’) => { console.log(‘then:’, ‘success1’); })
promise 的状态一旦改变就不能修改了,因此 .catch() 和第二个 resolve(‘success2’) 不会执行。

题目五

代码
1
2
3
4
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
答案
1
1
解读

.then() 中的参数必须是函数,如果是非函数,则会发生值穿透,最终执行第三个 .then() 函数,参数为 1。

题目六

代码
1
2
3
4
5
6
7
8
9
10
11
Promise.resolve(1)
.then((res) => {
console.log(res)
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res)
})
答案
1
2
1
2
解析
  1. promise.resolve() 返回一个新的 promise,执行第一个 .then(),参数为 1
  2. 打印 1,return 返回一个新的 promise,参数为 2
  3. 执行第二个 .then(),参数为 2,并打印出 2

题目七

代码
1
2
3
4
5
6
7
8
9
10
Promise.resolve()
.then(() => {
return new Error('error!!!')
})
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
1
then:  Error: error!!!
解析

这里的陷阱在于只有抛出错误时才会执行 .catch(),题目中并不是抛出错误,所以执行 .then()。

改成如下方式会执行 .catch():

1
2
3
return Promise.reject(new Error('error!!!'))
// 或者
throw new Error('error!!!')

题目八

代码
1
2
3
4
5
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(console.error)
答案

程序报错

1
TypeError: Chaining cycle detected for promise #<Promise>
解析

.then() 或 .catch() 返回的值不能是 promise 本身,否则会造成死循环。

题目九

代码
1
2
3
4
5
6
7
8
setTimeout(() => {
console.log(1)
Promise.resolve(3).then(data => console.log(data))
}, 0)

setTimeout(() => {
console.log(2)
}, 0)
答案
1
2
3
1
3
2
解读

先执行整体代码,没有发现微任务;
再执行下一个宏任务—setTimeout回调函数,打印出1;
遇到微任务—Promise 回调函数;
立即执行微任务,打印出3;
微任务队列被清空,执行下一个宏任务—下一个setTimeout回调函数,打印出2。

题目十

代码
1
2
3
4
5
6
7
8
9
10
11
12
var pro = new Promise((res, rej) => {
res(1);
});
pro.then(res => {
console.log(res);
});
setTimeout(() => {
console.log(2);
})
pro.then(res => {
console.log(res);
})
答案
1
2
3
1
1
2
解析

promise 对象赋值给了变量 pro,每个 .then() 都是独立的。

题目十一

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
async function async1() {
console.log('async1 start');
await async2();
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');
答案
1
2
3
4
5
6
7
8
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
解析

注意以下几点:

  1. 定义 async1(),async2(),不会立即执行
  2. await async2(); 表示先执行 async2(),然后将 await 后面的代码当作 .then() 中的回调来处理
  3. 初始化 promise,promise 中的代码会立即执行

转自:https://leetcode-cn.com/circle/discuss/sQXY3u/

  • 本文作者: David Xue
  • 本文链接: https://xdw-h.github.io/7/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!