【面试】Promise易错题

110 阅读3分钟

目的

记录做错的题,就像上学期间的错题本一样,错题错过一次后还是容易错,只有不断反复练习才会真正掌握,持续更新错题本。

题目一

new Promise((res,rej)=>{
   console.log(1);
   res(2);
   console.log(3)
   throw Error('abc')
}).catch((err)=>{
   console.log('123')
}).then((res)=>{
   console.log(res)
})

console.log('333')

可以看看上面题的输出顺序是什么?这里有个坑,resolve后再throw还会reject吗?就是被这个点给迷惑住了,我在想executor执行的时候是捕获了异常的,所以肯定是走到了reject中,但是,reject执行的时候是会判断当前promise的状态是不是pending,如果是pending才会变化,否则是不会执行的。

解答:

1、3、333、2

来吧,上规范,promisesaplus.com/, 还是说人话,直接中文吧。 【译】 Promises/A+ 规范

image.png

这道题还是答错了,之前以为promise掌握的不错了,一做题还是崩啊,所以这知识真是越学发现自己不会的越多。

题目二

 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);

知识点:resolve时状态更改和赋值是同步的,then的回调函数是异步的,所以promise1输出时是resolved的状态。

image.png

题目三

Promise.resolve(1)
    .then(2)
    .then(Promise.resolve(3))
    .then(console.log)

知识点: Promise.resolve的方法如果是一个原始值,则返回一个新对象状态为resolved,同时把值传递给回调函数,中间的都忽略。

1

题目四

async function async1() {
    console.log('async1 start');
    // 注意这里没有resolve
    await new Promise(resolve => {
        console.log('promise1')
    })
    console.log('async1 success');
    return 'async1 end';
}
console.log('script start')
async1().then(res => console.log(res))
console.log('script end');

易错点:await后的promise没有resolve,所以一直是pending状态

image.png

题目五

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

易错点:

  1. 代码多,需要仔细看
  2. 注意p和first的then调用顺序,p.then先调用所以它在前,
  3. resolve时会将promise状态变为success,并赋值,then是异步回调。
  4. 最后setTimeout里的console也是会打印出来。

image.png

题目六

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("resolve3");
    console.log("timer1");
  }, 0);
  resolve("resovle1");
  resolve("resolve2");
})
  .then((res) => {
    console.log(res);
    setTimeout(() => {
      console.log(p1);
    }, 1000);
    // return 1
  })
  .finally((res) => {
    console.log("finally", res);
  });

易错点

  1. 关于finally返回值,res是拿不到任何值的,所以是undefined
  2. p1是finally返回的promise,finally返回值在没有抛出错误的情况下,默认是上一个promise的返回值,这道题上一个promise是then,它没有返回任何内容, 则是undefined,如果加上return 1,则返回1

image.png

题目七

Promise.resolve().then(() =>{
    console.log('1');
    throw 'Error';
}).then(() => {
    console.log('2');
}).
catch(() => {
    console.log('3');
    throw 'Error';
}).then(() =>{
    console.log('4');
}).
catch(() => {
    console.log('5');
}).then(() =>{
    console.log('6');
});
  1. catch中抛出错误,也是会被后面的catch住

1、3、5、6

题目八

setTimeout(() => {
    console.log('timeout0');
    new Promise((resolve, reject) => { resolve('resolved') }).then(res => console.log(res));
    new Promise((resolve, reject) => {
      setTimeout(()=>{
        resolve('timeout resolved')
      })
    }).then(res => console.log(res));
    process.nextTick(() => {
        console.log('nextTick1');
        process.nextTick(() => {
            console.log('nextTick2');
        });
    });
    process.nextTick(() => {
        console.log('nextTick3');
    });
    console.log('sync');
    setTimeout(() => {
        console.log('timeout2');
    }, 0);
}, 0);

答案:

> timeout0
sync
nextTick1
nextTick3
nextTick2
resolved
timeout resolved
timeout2

题目九

setImmediate(function(){
    console.log("setImmediate");
    setImmediate(function(){
      console.log("嵌套setImmediate");
    });
    process.nextTick(function(){
      console.log("nextTick");
    });
    setTimeout(() => {
        console.log('settimeout')
    })
  });

image.png

题目十

async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')
  }
async function async2(){
    console.log('async2')
}
console.log('script start')
setTimeout(function(){
    console.log('setTimeout0') 
},0)  
setTimeout(function(){
    console.log('setTimeout3') 
},3)  
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick'));
async1();
new Promise(function(resolve){
    console.log('promise1')
    resolve();
    console.log('promise2')
}).then(function(){
    console.log('promise3')
})
console.log('script end')

image.png

最后三个setImmediate、setTimeout0、settimeout3 顺序不一定,每次运行可能不一样。

题目十一

setTimeout(() => {
  console.log("setTimeout 100");
  setTimeout(() => {
    console.log("setTimeout 100 - 0");
    process.nextTick(() => {
      console.log("nextTick in setTimeout 100 - 0");
    });
  }, 0);
  setImmediate(() => {
    console.log("setImmediate in setTimeout 100");
    process.nextTick(() => {
      console.log("nextTick in setImmediate in setTimeout 100");
    });
  });
  process.nextTick(() => {
    console.log("nextTick in setTimeout100");
  });
  Promise.resolve().then(() => {
    console.log("promise in setTimeout100");
  });
}, 100);

// const fs = require('fs')
// fs.readFile('./1.poll.js', () => {
//   console.log('poll 1');
//   process.nextTick(() => {
//     console.log('nextTick in poll ======');
//   })
// })

setTimeout(() => {
  console.log("setTimeout 0");
  process.nextTick(() => {
    console.log("nextTick in setTimeout");
  });
}, 0);

setTimeout(() => {
  console.log("setTimeout 1");
  Promise.resolve().then(() => {
    console.log("promise in setTimeout1");
  });
  process.nextTick(() => {
    console.log("nextTick in setTimeout1");
  });
}, 1);

setImmediate(() => {
  console.log("setImmediate");
  process.nextTick(() => {
    console.log("nextTick in setImmediate");
  });
});

process.nextTick(() => {
  console.log("nextTick 1");
  process.nextTick(() => {
    console.log("nextTick 2");
  });
});

console.log("global ------");

Promise.resolve().then(() => {
  console.log("promise 1");
  process.nextTick(() => {
    console.log("nextTick in promise");
  });
});

image.png

这里微任务执行完后,就会执行settimeout0、settimeout1、setImmediate在后面执行。

同时微任务是每执行完一个宏任务后就执行所有的微任务。