promise大厂面试真题总结

我在网上搜索大厂面经,总结了一些promise的经典面试题。希望能帮助到需要的同学。
更多题目,可以访问灵题库

关于promise的“说出代码执行结果”的面试题解题思路,可以参考我的另一篇文章:
一文讲透Promise面试题:说出代码执行结果

1. 说出代码执行结果(百度)

题目

说出下面代码执行结果

const promise = new Promise((resolve,reject)=>{
    console.log(1);
    resolve();
    console.log(2);
    reject()
})
setTimeout(()=>{console.log(5)},0)
promise.then(()=>{console.log(3)})
.then(()=>{console.log(6)})
.catch(()=>{console.log(7)})
console.log(4)
答案

答案是1,2,4,3,6,5
首先new Promise时候打印1和2,因为new Promise时候会立即执行传入的方法
然后后面代码都是异步代码,先将setTimeout的回调加入宏任务队列,再把promise.then放入到微任务队列,然后直接执行最后一句,打印4
这样宏任务代码执行完了,接下来开始执行微任务队列中的任务,由于promise resolve,因为promise resolve之后状态不会再改变,因此不会执行到reject的对调,所以打印3和6
微任务队列为空,再到宏任务队列中查找任务,找到setTimeout回调执行,打印5
调用栈、宏任务队列、微任务队列都为空,代码执行结束。

2. 说出代码执行结果(阿里)

题目

说出下面代码执行结果

const first = () => (new Promise((resolve, reject) => {
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        setTimeout(() => {
            console.log(5);
            resolve();
        }, 0);
        resolve(1);
    });
    resolve(2);
    p.then((arg) => {
        console.log(arg);
    });
}));
first().then((arg) => {
    console.log(arg);
});
console.log(4);
答案

3, 7, 4, 1, 2, 5
首先定义first
然后执行first,然后执行new Promise传入的方法,先打印3
又new Promise,执行其中传入的方法,打印7
执行setTimeout,将回调放入宏任务队列
执行resolve(1),将内部promise状态置为fullfilled,值为1
执行resolve(2),将外部promise状态置为fullfilled,值为2
执行内部promise.then方法,将回调加入微任务队列
执行first().then,即外部的promise,将回调加入到微任务队列
调用栈为空,开始从微任务队列拿取任务,首先拿到内部promise的回调,打印其值1
然后从微任务队列中拿取外部的promise的回调,打印其值2
此时微任务队列为空,开始从宏任务队列中拿取任务,即setTimeout回调,打印5。
调用栈,宏任务队列和微任务队列都为空,执行结束。

3. 说出代码执行结果(字节)

题目

说出下面代码执行结果

console.log(1);
new Promise(resolve => {
    resolve();
    console.log(2);
}).then(() => {
    console.log(3);
})
setTimeout(() => {
    console.log(4);
}, 0);
console.log(5);

答案

1,2,5,3,4
先打印1
执行new Promise的函数,打印2
执行promise.then,将回调加入微任务队列
将setTimeout的回调加入宏任务队列
打印5
调用栈为空,取微任务队列中的任务执行,打印3
微任务队列为空,取宏任务队列任务执行,打印5
调用栈、微任务队列、宏任务队列都为空,执行结束

4. 说出代码执行结果(字节)

题目

说出下面代码执行结果

Promise.resolve()
.then(() => {
    console.log('1');
})
.then(() => {
    console.log('2');
});


setTimeout(() => {
    Promise.resolve()
    .then(() => {
        console.log('3');
    })
    .then(() => {
        console.log('4');
    });
    setInterval(() => {
        console.log('5');
    }, 3000);
    console.log('6');
}, 0);
答案

1,2,6,3,4,5,5…
先执行Promise.resolve,将两个回调加入到微任务队列中
执行setTimeout,将其回调加入宏任务队列
调用栈为空,拿出微任务队列中的两个回调执行,打印1,2
微任务队列为空,拿出宏任务队列中的setTimeout的回调执行
将setTimeout中的Promise.resolve的两个回调加入到微任务队列
将setTimeout中的setInterval的回调加入宏任务队列
打印6
取出微任务队列中的两个Promise的回调,打印3,4
取宏任务队列中的setInterval的回调执行,每隔3s符合执行条件,打印5。注意setInterval调用时候不马上会执行一次,第一次执行是3s以后。

5. 说出代码执行结果(网易)

题目

说出代码执行结果

setTimeout(function() {
    console.log(1);
}, 0);
console.log(2);
async function s1() {
    console.log(7)
    await s2();
    console.log(8);
}
asycn function s2() {
    console.log(9);
}
s1();
new Promise((resolve, reject) => {
    console.log(3);
    resolve();
    console.log(6);
}).then(() => console.log(4))
console.log(5);
答案

2,7,9,3,6,5,8,4,1
记住async只是promise的语法糖,转化为等价的形式就好分析了
先执行setTimeout,加入宏任务队列中
打印2
执行s1,同步打印7
执行s2,同步打印3
执行完s2,将console.log(8)加入到微任务队列
然后执行s1后面的Promise,打印3和6
执行then,将console.log(4)加入到微任务队列中
打印5
调用栈为空,将微任务队列中的两个任务依次拿出来执行,打印8和4
微任务队列执行完,将宏任务队列的任务拿出来执行,打印1
调用栈、微任务队列、宏任务队列都为空,执行完毕。

6. 代码的执行结果(拼多多)

题目

说出下面代码执行结果

function fn() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
          reject('error');
      }, 1000);
  });
}
const foo = async () => {
   try {
     await fn();
  } catch (e) {
      console.log('lala', e);  // some error
  }
}
foo();
答案

打印 lala error。
如果await后面返回的promise reject掉,需要用try catch语句捕获这个reject。

7. 讲讲promise(字节、美团、拼多多)

题目

讲讲promise,promise的3种状态和状态转换。
Promise中回调函数是同步的还是异步的?then的链式调用是同步的还是异步的?

答案

promise目的:异步编程解决回调地狱,让程序开发者编写的异步代码具有更好的可读性。
promise规范规定了一种异步编程解决方案的API。规范规定了promise对象的状态和then方法。
promise是这种异步编程的解决方案的具体实现。

new Promise对象时候传入函数,函数立即执行,函数接收resolve、reject参数,调用resolve或reject时候会改变promise状态。状态改变后不会再变化。
promise状态

  • pending
  • fullfilled
  • rejected
    未调用resolve或者reject时候处于pending状态,调用resolve后处于fullfilled状态,调用reject后处于rejected状态。如果在pending状态时候,执行任务抛出错误,则变成reject状态。
    状态变化后,会执行通过then注册的回调。执行顺序和调用then方法的顺序相同。
    调用then方法时候,如果状态是pending则注册回调,等到状态改变时候执行,如果状态已经改变则执行相应的回调。

Promise回调函数是同步的,then回调是异步的,会被放到微任务队列中异步执行。

8. 手写promise(百度、拼多多、京东)

题目

手写promise

答案

参考这篇文章:
手写Promise

9. 实现Promise.all,Promise.race,Promise.any(百度、滴滴、网易)

题目

如何实现Promise.all、Promise.race和Promise.any方法。

答案

Promise.all,Promise.race,Promise.any的实现

function all(arr) {
    return new Promise((resolve, reject) => {
        let isComplete = false;
        const resolveDataList = new Array(arr.length).fill(undefined);
        const onFullfilled = (data, i) => {
            if (isComplete) {
                return;
            }
            resolveDataList[i] = data;
            if (resolveDataList.every(item => item !== undefined)) {
                resolve(resolveDataList);
            }
        };
        const onRejected = reason => {
            if (isComplete) {
                return;
            }
            isComplete = true;
            reject(reason);
        }
        arr.forEach((promise, index) => {
            promise.then(
                data => {onFullfilled(data, index)},
                onRejected
            );
        });
    });
}


function race(arr) {
    return new Promise((resolve, reject) => {
        let isComplete = false;
        const onFullfilled = data => {
            if (isComplete) {
                return;
            }
            isComplete = true;
            resolve(data);
        };
        const onRejected = reason => {
            if (isComplete) {
                return;
            }
            isComplete = true;
            reject(reason);
        };
        arr.forEach(promise => {
            promise.then(
                onFullfilled, onRejected
            );
        });
    });
}

function any(arr) {
    return new Promise((resolve, reject) => {
        let isComplete = false;
        const rejectDataList = new Array(arr.length).fill(undefined);
        const onFullfilled = data => {
            if (isComplete) {
                return;
            }
            isComplete = true;
            resolve(data);
        };
        const onRejected = (reason, i) => {
            if (isComplete) {
                return;
            }
            rejectDataList[i] = reason;
            if (rejectDataList.every(item => item !== undefined)) {
                reject('AggregateError: All promises were rejected');
            }
        }
        arr.forEach((promise, index) => {
            promise.then(
                onFullfilled,
                reason => {onRejected(reason, index);}
            );
        });
    });
}

10. Promise.all,Promise.race区别(拼多多)

题目

Promise.all,Promise.race区别是什么?
手写一个方法,使用Promise.all,实现所有都resolved/reject时才返回,并返回所有的结果

答案

区别是:
Promise.all() 全部promise成功才算成功,一个promise就算失败,成功的话,返回成功的数据数组,失败的话抛出最先失败的promise的reason。
Promise.race() 最先的promise完成则返回,promise结果和最先完成的promise一致。

手写方法:

function allComplete(arr) {
    return Promise.all(arr.map(promise => {
        return new Promise(
            resolve => promise.then(resolve, resolve)
        );
    }));
}

关注「灵题库」,更多大厂面试真题解析。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值