8个关于 Promise.then 和 Promise.catch 的面试题,一定要掌握

41a83045a4b95266e3e07db38cb08b91.jpeg

英文 | https://medium.com/frontend-canteen/10-code-challenges-to-master-promise-then-and-promise-catch-3da2bdea1d97

前面,我们要讨论了 Promise 在异步编程中的执行,错过的朋友可以直接点击《10 个 JavaScript Promise 的面试题》这篇文章进行查看。

在今天的文章中,我们将讨论这些核心 API 用于 Promise 对象的用法。

这里我提供了10个代码片段,你需要看一看这些程序的执行结果。

你准备好了吗?我们要开始了!

01、

const promise = new Promise((resolve, reject) => {
  resolve("success1");
  reject("fail");
  resolve("success2");
});


promise
.then(res => {
    console.log("then: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  })

此代码段的输出是什么?

分析

我们知道 Promise 可能是以下三种状态之一:

  • 待定:初始状态,既不履行也不拒绝。

  • 已完成:表示操作已成功完成。

  • 拒绝:表示操作失败。

dbb7a3af5ca3ab6a75153645a4fb4b84.png

状态只能从待处理变为已完成,或从待处理变为已拒绝。

这种变化是不可逆的。它不能从已完成变为待处理,也不能从拒绝变为待处理。同时,完成不能变成拒绝,拒绝也不能变成完成。

6e57637d86cfa7e43caa32d1b50a43a2.png

所以在上面的代码中,只有 resolve('success1') 是一个有效的操作。最后两个无效。

b239e4ed077738b0b3f6f6370e91ce97.png

结果

这是嵌入演示:

const promise = new Promise((resolve, reject) => {
  resolve("success1");
  reject("fail");
  resolve("success2");
});


promise
.then(res => {
    console.log("then: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  });

02、

const promise = new Promise((resolve, reject) => {
  reject("fail");
  resolve("success2");
});
promise
.then(res => {
    console.log("then1: ", res);
  }).then(res => {
    console.log("then2: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  }).then(res => {
    console.log("then3: ", res);
  })

此代码段的输出是什么?

分析

首先,无论catch方法放在哪里,都能捕捉到上层没有捕捉到的错误。

同时需要注意的是,catch 方法也会返回一个新的 Promise 对象,导致后面的 then 方法也被执行。

d4dbbdecdc5f1ada9b2d9b3ad6e9d3c5.png

结果

所以输出是:

catch:  fail
then3:  undefined

03、

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

此代码段的输出是什么?

分析

每个 .then() 方法的返回值都是一个新的 Promise。即使代码说 return 2,实际执行的是 return Promise.resolve(2) 。

36c6a11b0815c3834b9ed3a46438d446.png

结果

所以输出是:

1
2
undefined

04、

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

此代码段的输出是什么?

分析

这个挑战和上一个几乎一样,只是从 Promise.resolve 变成了 Promise.reject。所以执行流程会有一些变化。

c6a63ad27e23cb09fb3a7e22b1b4ad4a.png

结果

所以输出是:

3
undefined

05、

const promise = new Promise((resolve, reject) => {
    resolve(1)
})


promise.then(res => {
  console.log('first then: ', res)
  return 2
})


promise.then(res => {
  console.log('second then: ', res)
  return 3
})


promise.then(res => {
  console.log('third then: ', res)
})

此代码段的输出是什么?

分析

记住一条铁律:一旦确定了 Promise 的状态,就无法更改。

同样在这个题中,那些 .then() 不是链式调用,它们都是对 promise 对象的调用。

05950a24edbee7cacad93cfac9b3ef1c.png

结果

所以输出是:

1
1
1

06、

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

此代码段的输出是什么?

分析

小心这个挑战。

new Error() 是一个普通的 JavaScript 对象,return 是一个普通的 JavaScript 关键字,所以这段代码会正常工作,不会抛出异常。

它将返回一个已完成状态且值为 new Error('error!!!') 的对象。

00424250dcf78e36f5817ceac692de7a.png

所以输出是:

then:  Error: error!!!

当然,如果你想抛出错误,你可以使用以下任一方法:

return Promise.reject(new Error('error!!!'));
// or
throw new Error('error!!!')

07、

const promise = Promise.resolve().then(() => {
  return promise;
})


promise.catch(console.err)

此代码段的输出是什么?

分析

.then 或 .catch 返回的值不能是 Promise 本身,否则会导致死循环。

所以代码会抛出异常:

TypeError: Chaining cycle detected for promise #<Promise>}

b0fb91af1ceab0c7caf7f36a5eadbf20.png

08、

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

此代码段的输出是什么?

分析

这个问题看似简单,但其实大部分人的答案都是错误的。

  • .then 或 .catch 的参数应该是一个函数。

  • 如果参数不是函数,则此 .then 或 .catch 将被忽略。

950e9fbe6e9f2503e6ca58d74d4af4f3.png

总结

以上就是我今天跟你分享的全部内容,希望这个内容对你有所帮助,最后,感谢你的阅读。

学习更多技能

请点击下方公众号

3e145fb9df97596d62a8ed5bf5aaa190.gif

756cbe3a6eb689e7b4415befebf3ce0c.jpeg

6125f9554226b1123677ee1ba674dd48.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值