ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分析promise面试题

2022-08-31 22:31:23  阅读:200  来源: 互联网

标签:分析 面试题 resolve console log res value Promise promise


Promise面试题地址: https://mp.weixin.qq.com/s/SIeDvm8nYDPK5XWzRj7LCg

Promises/A+规范: https://promisesaplus.com/

Promise的一个实现: https://github.com/taylorhakes/promise-polyfill.git

名词解释

  • onFulfilled: then的第一个参数, 默认提供函数
  • onRejected: then的第二个参数, 默认提供函数

第一题

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })
1 2

首先, Promise.resolve原理如下:

Promise.resolve = function (value) {
    if (value && typeof value === 'object' && value.constructor === Promise) {
        return value
    }
    return new Promise((resolve) => { resolve(value) })
}

因为传入的value是1, 所以题目可以转化为:

new Promise((resolve) => { resolve(1) })
    .then((res) => {
        console.log(res)
        return 2
    })
    .catch((err) => {
        return 3
    })
    .then((res) => {
        console.log(res)
    })

同时, catch原理如下:

Promise.prototype.catch = function (onReject) {
    return this.then(null, onReject)
}

所以题目可以继续转化为:

new Promise((resolve) => { resolve(1) })
    .then((res) => {
        console.log(res)
        return 2
    })
    .then(null, (err) => {
        return 3
    })
    .then((res) => {
        console.log(res)
    })

从中可以看出, 一共有四个Promise:

  • 第一个Promise: 从resolve(1)可以看出, 自身Promise状态从pending转化为fulfilled, value = 1
  • 第二个Promise: 因为第一个Promise的状态是fulfilled, 所以它的value是onFulfilled函数的第一个参数, 即 res = 1; 因为onFulfilled函数返回一个x, 且x既不是函数也不是对象, 所以自身Promise状态从pending转化为fulfilled, value = 2
  • 第三个Promise: 因为onFulfilled不是一个函数, 所以自身状态从pending转换为fulfilled, value是第二个Promise的value, 即 value = 2
  • 第四个Promise: 因为第三个Promise的状态是fulfilled, 所以它的value是onFulfilled函数的第一个参数, 即 res = 2;

从上面分析可知: 程序最终会打印 1 和 2

第二题

const promise = new Promise((resolve, reject) => {
    console.log(1)
    resolve()
    console.log(2)
})
promise.then(() => {
    console.log(3)
})
console.log(4)
1 2 4 3

首先, promise初始化时会传入一个函数x, 如下所示:

(resolve, reject) => {
    console.log(1)
    resolve()
    console.log(2)
}

x函数会被执行一次, 但resolve函数涉及Promise的状态转变, 而Promise自身是一个微任务, 所以resolve的执行被放到微任务队列里面, 等目前执行栈为空再清空微任务队列, 所以会首先打印 1 和 2, 此时Promise的状态还是pending, then函数的onFulfilled会存进第一个Promise的回调函数队列中, 然后打印 4, 此时执行栈空了, 开始清空微任务队列, Promise的状态从pending转为fulfilled, 同时清空自身回调函数队列, 最后打印 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)

首先, promise1初始化时传入了一个函数x, 如下所示:

(resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 1000)
}

x函数会被执行一次, 因为setTimeout是一个宏任务, 所以会存在宏任务队列里

然后, promise2需要等待promise1的状态转变, 因此onFulfilled函数存进promise1的回调函数队列中, 此时打印promise1 和 promise2会显示Promise的pending状态

程序继续执行, 打印语句也会存进宏任务队列里, 因为延时是2000, 大于1000, 所以会在第一个setTimeout函数后面执行, 打印 promise1 的fulfilled状态和promise2 的reject状态; 如果延时是500, 则会提前执行, 还是会打印promise1 和 promise2会显示Promise的pending状态

按照我的理解, promise2中抛出的异常会被捕获到, 因此不会打印警告, 实际情况如下:

  • 谷歌浏览器 version: 104.0.5112.101

img.png

标签:分析,面试题,resolve,console,log,res,value,Promise,promise
来源: https://www.cnblogs.com/silbernitrat07/p/16644751.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有