持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
前言
Promise.resolve(1).then(2).then(console.log).catch(console.log) 的将会在浏览器打印出什么?这是网络上众多面经中的一道面试题,主要是考察对 Promise.prototype.then() 的了解。
运行结果
原以为 then 的参数只能是两个函数,传入 2 之后,会因为 2 不是一个函数报错,从而触发 catch。
然而,直接在浏览器跑一下代码,最终在浏览器控制台打印出一个 1。
为什么
在 MDN 中,有这么一句话:
当 Promise 变成接受状态(fulfilled)时调用的
函数。该函数有一个参数,即接受的最终结果(the fulfillment value)。如果该参数不是函数,则会在内部被替换为(x) => x,即原样返回 promise 最终结果的函数。
当 then 的第一个参数不是函数时,会在内部被替换成 (x) => x。
也就是说,上面的 then(2) 会在内部被处理成 then((x) => x),所以这个步骤只会返回 Promise.resolve 或者上一个 then 的返回值,不会报错,也不会进行任何特殊的处理。
又因为 Promise.resolve(1),所以 then(2) 其实就是 then((1) => 1)。
最终 then(console.log(1)),会在浏览器打印出 1。
而 then 的关于第二个参数,如果不是一个函数,也是同样的道理,不过会被替换为一个 Thrower 函数,继续抛出错误或者是 Promise.reject(),直到有其他代码对该错误进行处理为止。
注意:如果是
Promise.reject(1).then((x) =>x, (err) => err).then(console.log)这种写法,则最终还是由第二个then打印出结果,因为第一个then的错误处理函数的返回值,会作为第二个then的参数,这也是为什么then的第二个参数会被替换为一个Thrower函数,抛出错误,而不是返回错误。