JS 异步(下)部分面试题分析

JS 异步(下)部分面试题分析

 

4.promise 中 then 和 catch 的连接

 

4.1 第一题
Promise.resolve().then(() => {
  console.log(100);
}).catch(() => {
  console.log(200);
}).then(() => {
  console.log(300);
});

输出:100,300

分析:

  1. 因为执行的是 promise 的 resolve 函数,则触发第一个 then ,由此执行第 3 行,输出 100;
  2. 第一个 then 在执行后,未抛出错误,则不会触发最近的 catch,会直接触发最近的 then ,则执行第 7 行 ,输出 300;

 

4.2 第二题
Promise.resolve().then(() => {
  console.log(400);
  throw new Error('error1')
}).catch(() => {
  console.log(500);
}).then(() => {
  console.log(600);
});

输出:400,500,600

分析:

  1. 因为执行的是 promise 的 resolve 函数,则触发第一个 then ,由此执行第 3 行,输出 400;
  2. 第一个 then 在执行后,抛出错误,触发最近的 catch,执行第 6 行 ,输出 500
  3. 在 catch 中未抛出异常,则会触发紧邻的 then ,即执行第 8 行,输出 600;

注:关于第 3 点,不理解的可以再看看 JS 异步进阶 5.3 节 第 5 点的 then 和 catch 对状态的影响
 

4.3 第三题
Promise.resolve().then(() => {
  console.log(700);
  throw new Error('error2')
}).catch(() => {
  console.log(800);
}).catch(() => {
  console.log(900);
});

输出:700,800

分析:

  1. 因为执行的是 promise 的 resolve 函数,则触发第一个 then ,由此执行第 3 行,输出 700;
  2. 第一个 then 在执行后,抛出错误,触发紧邻的 catch,执行第 6 行 ,输出 800
  3. 在 catch 中未抛出异常,则只会触发紧邻的 then,不会触发catch ;
4.4 附加题:将上面三个 promise 放在一起执行,给出输出结果
Promise.resolve().then(() => {
  console.log(100); // 1
}).catch(() => {
  console.log(200);
}).then(() => {
  console.log(300); // 6
});

Promise.resolve().then(() => {
  console.log(400); // 2
  throw new Error('error1')
}).catch(() => {
  console.log(500); // 4
}).then(() => {
  console.log(600); // 7
});

Promise.resolve().then(() => {
  console.log(700); // 3
  throw new Error('error2')
}).catch(() => {
  console.log(800); // 5
}).catch(() => {
  console.log(900);
});
// 100,400,700,500,800,300,600

分析:

  1. 按顺序,第 1,9, 18行首先执行 resolve 函数,then 函数依次进入微任务队列(第一梯队),随后根据微任务队列顺序执行;
  2. 执行第 2 行,输出 100,触发第 5 行 then,进入微任务队列等待执行(第二梯队);
  3. 执行第 10 行,输出 400,抛出异常,触发第 12 行 catch ,等待第一梯队微任务执行完就马上执行;
  4. 执行第 19 行,输出 700,抛出异常,触发第 24 行 catch ,等待第一梯队微任务执行完就马上执行;
  5. 第一梯队任务执行完,依次触发 12,24 行 cath ,输出 500, 800,注意,触发完 12 行 catch 后,触发第 14 行 then,进入微任务队列(第二梯队);
  6. 按顺序执行第二梯队微任务,输出 300 ,600;
     
5.async 和 await 语法题

 

5.1 第一题
async function fn() {
  return 100;
};
async function excute() {
  const res1 = fn();
  const res2 = await fn();
  console.log('res1:', res1);
  console.log('res2:', res2);
}
excute();	// res1, res2 的内容

输出:res1: Promise {: 100}
res2: 100

分析:

  1. 直接执行 async 函数,会返回一个 Promise 对象;
  2. await 相当于 promise 的then(不会走catch), 返回的是then的参数,处理的是成功的情况
     
5.2 第二题
async function excute() {
  console.log('start');
  const res1 = await 100;
  console.log('res1:', res1);
  const res2 = await Promise.resolve(200)
  console.log('res2:', res2);
  const res3 = await Promise.reject(300)
  console.log('res3:', res3);
  console.log('end');
}
excute();// 打印内容

输出:
start
res1: 100
res2: 200
Uncaught (in promise) 300

分析:

  1. await 加数据类型,直接返回该数据类型的值;
  2. await 相当于 promise 的 then,返回的是 then 的参数,即200
  3. Promise.reject,抛出错误,程序停止执行
     
6. promise 和 setTimeout 的顺序
console.log(100);
setTimeout(() => {
  console.log(200);
}, 0);
Promise.resolve().then(() => {
  console.log(300);
});
console.log(400);

输出:100,400,300,200

分析:

  1. 首先执行第 1 行,输出 100;
  2. 执行到 setTimeout ,放进 web APIs 开始计时,完成计时后就放进任务队列等待执行;
  3. 执行到 Promise.resolve,触发第 1 个 then,放进微任务队列等待执行;
  4. 执行第 6 行,输出 400;
  5. 轮询微任务队列,执行第 6 行,输出 300;
  6. 轮询任务队列,执行第 3 行,输出 200;
     
7.promise 和 async / await 的顺序问题
async function asyncFn1() {
  console.log('asyncFn1 excute');
  await asyncFn2();
  console.log('asyncFn1 end');
}

async function asyncFn2() {
  console.log('asyncFn2 excute');
}

console.log('script start');

setTimeout(() => {
  console.log('setTimeout');
});

asyncFn1();

new Promise ((resolve) => {
  console.log('promise excute');
  resolve();
}).then(() => {
  console.log('then excute');
});

console.log('script end');

输出:
script start
asyncFn1 excute
asyncFn2 excute
promise excute
script end
asyncFn1 end
then excute
setTimeout

分析:

  1. 首先执行第 11 行,输出 script start;
  2. 执行到第 13 行 setTimeout,放入 web APIs 中开始计时,计时完成放进任务队列;
  3. 执行第 17 行 asyncFn1 函数,进入 asyncFn1 函数;
  4. 执行第 2 行,输出 asyncFn1 excute;
  5. 执行第 3 行 asyncFn2 函数,进入 asyncFn2 函数,第 4 行进入微任务队列等待执行(这是因为在 await 后面执行的代码,都可以看作是 await 后的异步代码(微任务),需要等待同步执行完后才能执行)
  6. 执行第 8 行,输出 asyncFn2 excute;,退出 asyncFn2 函数,退出 asyncFn1 函数;
  7. 执行第 19 行 promise,直接执行第 20 行,输出 promise excute;第 22 行进入微任务队列;
  8. 执行第 26 行,输出 script end;
  9. 轮询微任务队列,按顺序依次输出 asyncFn1 end,then excute;
  10. 轮询任务队列,执行第 14 行,输出 setTimeout;

至此,程序执行结束。

欢迎大家点赞,收藏,关注!!!

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值