前言
对于 Promise 的解说文章切实太多了,在此我就不写解说了,间接实战检测本人对 Promise 的了解,上面是我做过的泛滥 Promise 题外面挑出来的 13 道题,我感觉容易错或者值得讲究知识点的题,如果你想考查本人对 Promise 的把握水平,能够做做看。
这些题是我从上面两个链接的题目又选出来的,仅作为本人的错题集/笔记题来记录,不便当前我本人测验回顾。如果你想更全面学,倡议间接去做上面两篇的题。
特地鸣谢
- 【倡议星星】要就来 45 道 Promise 面试题一次爽到底(1.1w 字用心整顿)
- 八段代码彻底把握 Promise
题目 1
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)
剖析:
- 先遇到
new Promise
,执行该构造函数中的代码输入promise1
- 遇到
resolve
函数, 将promise1
的状态扭转为fulfilled
, 并将后果保留下来 - 碰到
promise1.then
这个微工作,返回的是Promise
的pending
状态,将它放入微工作队列 - 故
promise2
是一个新的状态为pending
的Promise
- 继续执行同步代码输入
promise1
的状态是fulfilled
,输入promise2
的状态是pending
- 宏工作执行结束,查找微工作队列,发现
promise1.then
这个微工作且状态为fulfilled
,执行它。
输入后果:
promise11 Promise{<fulfilled>: 'resolve1'}2 Promise{<pending>}resolve1
题目 2
const promise = new Promise((resolve, reject) => { console.log(1) setTimeout(() => { console.log('timerStart') resolve('success') console.log('timerEnd') }, 0) console.log(2)})promise.then(res => { console.log(res)})console.log(4)
剖析:
- 执行
new Promsise
,输入1
,setTimeout
宏工作加到宏工作队列,继续执行同步代码输入2
- 遇到
promise.then
,但其状态还是 pending,这里了解为先不执行;而后输入同步代码4
- 一轮循环过后,进入第二次宏工作,发现提早队列中有
setTimeout
定时器,执行它 - 输入
timerStart
,遇到resolve
,将promise
的状态改为fulfilled
且保留后果并将之前的promise.then
推入微工作队列 - 继续执行同步代码
timerEnd
- 宏工作全副执行结束,查找微工作队列,发现
promise.then
这个微工作,执行它。
输入后果:
124timerStarttimerEndsuccess
题目 3
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') }, 1000)})const promise2 = promise1.then(() => { throw new Error('error!!!')})console.log('promise1', promise1)console.log('promise2', promise2)setTimeout(() => { console.log('promise1', promise1) console.log('promise2', promise2)}, 2000)
剖析:
- 从上至下,先执行第一个
new Promise
中的函数,碰到setTimeout
将它退出下一个宏工作列表 - 跳出
new Promise
,碰到promise1.then
这个微工作,但其状态还是为pending
,这里了解为先不执行;故promise2
是一个新的状态为pending
的Promise
- 执行同步代码
console.log('promise1')
,输入promise1
的状态为pending
- 执行同步代
console.log('promise2')
,输入promise2
的状态为pending
- 碰到第二个
setTimeout
,将其放入下一个宏工作列表 - 第一轮宏工作执行完结,并且没有微工作须要执行,因而执行第二轮宏工作
- 先执行第一个定时器里的内容,将
promise1
的状态改为fulfilled
且保留后果并将之前的promise1.then
推入微工作队列 - 该定时器中没有其它的同步代码可执行,因而执行本轮的微工作队列,也就是
promise1.then
,它抛出了一个谬误,且将promise2
的状态设置为了rejected
- 第一个定时器执行结束,开始执行第二个定时器中的内容
- 打印出
promise1
,且此时promise1
的状态为fulfilled
- 打印出
promise2
,且此时promise2
的状态为rejected
promise1 Promise {<pending>}promise2 Promise {<pending>}Uncaught (in promise) Error: error!!! at <anonymous>:7:9promise1 Promise {<fulfilled>: "success"}promise2 Promise {<rejected>: Error: error!!! at <anonymous>:7:9}
题目 4
const promise = new Promise((resolve, reject) => { reject('error') resolve('success2')})promise .then(res => { console.log('then1: ', res) }) .then(res => { console.log('then2: ', res) }) .catch(err => { console.log('catch: ', err) }) .then(res => { console.log('then3: ', res) })
剖析:
catch
不论被连贯到哪里,都能捕捉下层未捕获过的谬误。- 因为
catch()
也会返回一个Promise
,且因为这个Promise
没有返回值,所以打印进去的是undefined
。
输入后果:
catch: errorthen3: undefined
题目 5
Promise.resolve() .then(() => { return new Error('error!!!') }) .then(res => { console.log('then: ', res) }) .catch(err => { console.log('catch: ', err) })
剖析:
- 在
Promise
中,返回任意一个非promise
的值都会被包裹成promise
对象,例如return new Error('error!!!')
会被包装为return Promise.resolve(new Error('error!!!'))
.then
或者.catch
中return
一个error
对象并不会抛出谬误,所以不会被后续的.catch
捕捉。
当然如果你抛出一个谬误的话,能够用上面任意一种:
return Promise.reject(new Error('error!!!'))// orthrow new Error('error!!!')
输入后果:
then: Error: error!!!
题目 6
const promise = Promise.resolve().then(() => { return promise})promise.catch(console.err)
剖析:
.then
或.catch
返回的值不能是promise
自身,否则会造成死循环。
输入后果:
Promise {<rejected>: TypeError: Chaining cycle detected for promise #<Promise>}
题目 7
Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
剖析:
.then
或者.catch
的参数冀望是函数,传入非函数则会产生值透传。- 第一个
then
和第二个then
中传入的都不是函数,一个是数字类型,一个是对象类型,因而产生了透传,将resolve(1)
的值间接传到最初一个then
里。
输入后果:
1
题目 8
Promise.reject('err!!!') .then( res => { console.log('success', res) }, err => { console.log('error', err) } ) .catch(err => { console.log('catch', err) })
剖析:
.then
函数的第一个参数是用来解决Promise
胜利的函数,第二个则是解决失败的函数。Promise.resolve('err!!!')
的值会进入胜利的函数,Promise.reject('err!!!')
的值会进入失败的函数。- 如果去掉第二个参数,就会进入
catch()
中
输入后果:
'error' 'error!!!'
题目 9
Promise.resolve('1') .then(res => { console.log(res) }) .finally(() => { console.log('finally') })Promise.resolve('2') .finally(() => { console.log('finally2') return '我是finally2返回的值' }) .then(res => { console.log('finally2前面的then函数', res) })
剖析:
.finally()
办法不论Promise
对象最初的状态如何都会执行- 它最终返回的默认会是一个上一次的
Promise
对象值,不过如果抛出的是一个异样则返回异样的Promise
对象。 - 第一行代码遇到
Promise.resolve('1')
,再把.then()
退出微工作,这时候要留神,代码并不会接着往链式调用的上面走,也就是不会先将.finally
退出微工作列表,那是因为.then
自身就是一个微工作,它链式前面的内容必须得等以后这个微工作执行完才会执行,因而这里咱们先不论.finally()
- 执行
Promise.resolve('2')
,把.finally
退出微工作队列,且链式调用前面的内容得等该工作执行完后才执行 - 本轮宏工作执行完,执行微工作列表第一个微工作输入
1
,遇到.finally()
,将它退出微工作列表(第三个)待执行;再执行第二个微工作输入finally2
,遇到.then
,把它退出到微工作(第四个)列表待执行 - 本轮执行完两个微工作后,检索微工作列表发现还有两个微工作,故执行,输入
finally
和finally2前面的then函数 2
输入后果:
1finally2finallyfinally2前面的then函数 2
题目 10
async function async1() { console.log('async1 start') await new Promise(resolve => { console.log('promise1') }) console.log('async1 success') return 'async1 end'}console.log('srcipt start')async1().then(res => console.log(res))console.log('srcipt end')
剖析:
- 在
async1
中await
前面的Promise
是没有返回值的,也就是它的初始状态是pending
状态,因而相当于始终在await
- 所以在
await
之后的内容是不会执行的,也包含async1
前面的.then
。
输入后果:
srcipt startasync1 startpromise1srcipt end
题目 11
async function async1() { await async2() console.log('async1') return 'async1 success'}async function async2() { return new Promise((resolve, reject) => { console.log('async2') reject('error') })}async1().then(res => console.log(res))
剖析:
await
前面跟着的是一个状态为rejected
的promise
。- 如果在
async
函数中抛出了谬误,则终止谬误后果,不会持续向下执行。
输入后果:
async2Uncaught (in promise) error
题目 12
var p1 = new Promise(function (resolve, reject) { foo.bar() resolve(1)})p1.then( function (value) { console.log('p1 then value: ' + value) }, function (err) { console.log('p1 then err: ' + err) }).then( function (value) { console.log('p1 then then value: ' + value) }, function (err) { console.log('p1 then then err: ' + err) })var p2 = new Promise(function (resolve, reject) { resolve(2)})p2.then( function (value) { console.log('p2 then value: ' + value) foo.bar() }, function (err) { console.log('p2 then err: ' + err) }) .then( function (value) { console.log('p2 then then value: ' + value) }, function (err) { console.log('p2 then then err: ' + err) return 1 } ) .then( function (value) { console.log('p2 then then then value: ' + value) }, function (err) { console.log('p2 then then then err: ' + err) } )
剖析:
Promise 中的异样由 then 参数中第二个回调函数(Promise 执行失败的回调)解决,异样信息将作为 Promise 的值。异样一旦失去解决,then 返回的后续 Promise 对象将恢复正常,并会被 Promise 执行胜利的回调函数解决。另外,须要留神 p1、p2 多级 then 的回调函数是交替执行的 ,这正是由 Promise then 回调的异步性决定的。
输入后果:
p1 then err: ReferenceError: foo is not definedp2 then value: 2p1 then then value: undefinedp2 then then err: ReferenceError: foo is not definedp2 then then then value: 1
题目 13
var p1 = new Promise(function (resolve, reject) { resolve(Promise.resolve('resolve'))})var p2 = new Promise(function (resolve, reject) { resolve(Promise.reject('reject'))})var p3 = new Promise(function (resolve, reject) { reject(Promise.resolve('resolve'))})p1.then( function fulfilled(value) { console.log('fulfilled: ' + value) }, function rejected(err) { console.log('rejected: ' + err) })p2.then( function fulfilled(value) { console.log('fulfilled: ' + value) }, function rejected(err) { console.log('rejected: ' + err) })p3.then( function fulfilled(value) { console.log('fulfilled: ' + value) }, function rejected(err) { console.log('rejected: ' + err) })
剖析:
Promise 回调函数中的第一个参数 resolve,会对 Promise 执行"拆箱"动作。即当 resolve 的参数是一个 Promise 对象时,resolve 会"拆箱"获取这个 Promise 对象的状态和值,但这个过程是异步的。p1"拆箱"后,获取到 Promise 对象的状态是 resolved,因而 fulfilled 回调被执行;p2"拆箱"后,获取到 Promise 对象的状态是 rejected,因而 rejected 回调被执行。但 Promise 回调函数中的第二个参数 reject 不具备”拆箱“的能力,reject 的参数会间接传递给 then 办法中的 rejected 回调。因而,即便 p3 reject 接管了一个 resolved 状态的 Promise,then 办法中被调用的仍然是 rejected,并且参数就是 reject 接管到的 Promise 对象。
输入后果:
p3 rejected: [object Promise]p1 fulfilled: resolvep2 rejected: reject
- ps: 集体技术博文 Github 仓库,感觉不错的话欢送 star,给我一点激励持续写作吧~