promise面试题

1.

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。

解题思路:then方法是异步执行的。

2.

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
    reject('error')
  }, 1000)
})
promise.then((res)=>{
  console.log(res)
},(err)=>{
  console.log(err)
})
//  输出结果:success

解题思路:Promise状态一旦改变,无法在发生变更。

3.

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
//  输出结果:1

解题思路:Promise的then方法的参数期望是函数,传入非函数则会发生值穿透。

4.

setTimeout(()=>{
  console.log('setTimeout')
})
let p1 = new Promise((resolve)=>{
  console.log('Promise1')
  resolve('Promise2')
})
p1.then((res)=>{
  console.log(res)
})
console.log(1)

//输出结果:
 // Promise1
  //1
  //Promise2
  //setTimeout

  解题思路:这个牵扯到js的执行队列问题,整个script代码,放在了macrotask queue中,执行到setTimeout时会新建一个macrotask queue。但是,promise.then放到了另一个任务队列microtask queue中。script的执行引擎会取1个macrotask queue中的task,执行之。然后把所有microtask queue顺序执行完,再取setTimeout所在的macrotask queue按顺序开始执行。

5.

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

 // 输出结果:1  2

  解题思路:Promise首先resolve(1),接着就会执行then函数,因此会输出1,然后在函数中返回2。因为是resolve函数,因此后面的catch函数不会执行,而是直接执行第二个then函数,因此会输出2。

6.

const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    console.log('开始');
    resolve('success');
    }, 5000);
});
 
const start = Date.now();
promise.then((res) => {
console.log(res, Date.now() - start);
});
 
promise.then((res) => {
console.log(res, Date.now() - start);
});
//  5s后输出结果:
    //开始
    //success 5002 或5001
    //success 5002 或5001

解题思路:promise 的.then或者.catch可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,then中的回调就会被调用。那么后续每次调用.then 或者.catch都会直接拿到该值。

7.

let p1 = new Promise((resolve,reject)=>{
  let num = 6
  if(num<5){
    console.log('resolve1')
    resolve(num)
  }else{
    console.log('reject1')
    reject(num)
  }
})
p1.then((res)=>{
  console.log('resolve2')
  console.log(res)
},(rej)=>{
  console.log('reject2')
  let p2 = new Promise((resolve,reject)=>{
    if(rej*2>10){
      console.log('resolve3')
      resolve(rej*2)
    }else{
      console.log('reject3')
      reject(rej*2)
    }
  })
  return p2
}).then((res)=>{
  console.log('resolve4')
  console.log(res)
},(rej)=>{
  console.log('reject4')
  console.log(rej)
})

  /*输出结果:

    reject1
    reject2
    resolve3
    resolve4
    12
*/

解题思路:我们上面说了Promise的先进之处在于可以在then方法中继续写Promise对象并返回。

8.重头戏!!!!实现一个简单的Promise

function Promise(fn){
  var status = 'pending'
  function successNotify(){
      status = 'fulfilled'//状态变为fulfilled
      toDoThen.apply(undefined, arguments)//执行回调
  }
  function failNotify(){
      status = 'rejected'//状态变为rejected
      toDoThen.apply(undefined, arguments)//执行回调
  }
  function toDoThen(){
      setTimeout(()=>{ // 保证回调是异步执行的
          if(status === 'fulfilled'){
              for(let i =0; i< successArray.length;i ++)    {
                  successArray[i].apply(undefined, arguments)//执行then里面的回掉函数
              }
          }else if(status === 'rejected'){
              for(let i =0; i< failArray.length;i ++)    {
                  failArray[i].apply(undefined, arguments)//执行then里面的回掉函数
              }
          }
      })
  }
  var successArray = []
  var failArray = []
  fn.call(undefined, successNotify, failNotify)
  return {
      then: function(successFn, failFn){
          successArray.push(successFn)
          failArray.push(failFn)
          return undefined // 此处应该返回一个Promise
      }
  }
}

解题思路:Promise中的resolve和reject用于改变Promise的状态和传参,then中的参数必须是作为回调执行的函数。因此,当Promise改变状态之后会调用回调函数,根据状态的不同选择需要执行的回调函数。

9.

Promise.resolve()
.then(() => {
    return new Error('error!!!')
})
.then((res) => {
    console.log('then: ', res)
})
.catch((err) => {
    console.log('catch: ', err)
})

/*结果
then:  Error: error!!!
    at Promise.resolve.then (<anonymous>:3:8)
    at <anonymous>
*/

解释:.then 或者 .catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获,需要改成其中一种:

(1)return Promise.reject(new Error(‘error!!!’))

(2)throw new Error(‘error!!!’)

因为返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error(‘error!!!’) 等价于 return Promise.resolve(new Error(‘error!!!’))。

9.

const promise = Promise.resolve()
.then(() => {
    return promise
})
promise.catch(console.error)

/*结果
TypeError: Chaining cycle detected for promise #<Promise>
    at <anonymous>*/

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

10.

const promise1 = new Promise((resolve,reject)=>{
	setTimeout(function(){
		resolve('success');
	},1000);
});

const promise2 = promise1.then(()=>{
	throw new Error('error');
});

console.log("promise1",promise1);
console.log("promise2",promise2);

setTimeout(function(){
	console.log("promise1",promise1);
	console.log("promise2",promise2);
},2000);
/*结果
 promise1 Promise {<pending>}
 promise2 Promise {<pending>}
 Uncaught (in promise) Error: error
   
 promise1 Promise {<resolved>: "success"}
 promise2 Promise {<rejected>: Error: error
   
Table of Contents