前言
前段时间的面试中,发现面试官是经常提出对于 Promise 相关的问题。于是本人开始决定来表达自己对于 Promise 的理解。
什么是Promise
首先还是我们的 是什么。Promise 是JavaScript中用于处理异步操作的一种解决方案。它可以通过对象的状态来管理异步操作的结果,并提供了一种更加优雅和可靠的方式来处理异步代码。
在 Promise 中有着三种初始状态,分别是:
pending: 这是初始状态,表示异步任务正在处理,状态还没有改变;fulfilled: 这是表示异步操作处理成功的标识;rejected: 这是表示异步操作处理失败的标识。
在 Promise 中,它接受两个参数 resolve 和 reject 。通过 resolve 我们可以将异步操作成功后的结果返回出去,与此同时状态也会改变为 fulfilled,同理,通过 reject 我们可以将异步操作失败后的结果返回出去,与此同时状态也会改变为 rejected。但是需要注意 :状态一经改变后就不能再次发生改变了,也就是说 resolve 和 reject 只能执行一个。
对于 resolve 出来的值,我们可以在 Promise 对象后加上 .then() 来获取异步操作处理成功所获得的结果,也可以通过 .catch() 来获取异步操作处理失败的结果。
Promise它有哪些方法
对于Promise来说,它身上有着如下的方法:
.then(): 这个之前我们也浅略的讲解过一下,这是 Promise 实例最常用的方法之一。它接受两个参数,分别是onFulfilled和onRejected,它们分别是在 Promise 状态变为fulfilled和Rejected时被调用的回调函数。then()方法返回一个新的 Promise 对象,可以用于链式调用。.catch():这个方法用于捕获 Promise 链中的错误,相当于then(null, onRejected)的简写形式。如果 Promise 状态变为rejected且没有被捕获,则会调用指定的onRejected回调函数。.finally:finally()方法用于指定不管 Promise 状态如何都会执行的回调函数onFinally。无论 Promise 是 fulfilled 还是 rejected,onFinally回调函数都会被执行。.all():这个方法主要是用于判断是否所有的异步操作都是成功的。该方法接收一个可迭代对象(比如数组)作为参数,返回一个新的 Promise 对象。当传入的所有 Promise 都成功完成时,返回的 Promise 对象才会被成功解析,解析值是一个包含所有 Promise 结果的数组。如果传入的任何一个 Promise 失败,则返回的 Promise 对象会立即被拒绝,拒绝原因是第一个失败的 Promise 的错误信息。.race():该方法也是接收一个可迭代对象作为参数。只要传入的参数中有一个Promise状态发生改变,它就会返回这个Promise的解析,无论它是成功还是失败的。.any():该方法也是接收一个可迭代对象作为参数。如果参数中有一个对象的状态变更为fulfilled他则返回这个对象的值,否则返回一个包含所有错误原因的数组。.allSettle():该方法也是接收一个可迭代对象作为参数。当传入的所有 Promise 都已经成功或失败时,返回的 Promise 对象会被解析,其值是一个包含每个 Promise 结果的对象数组,每个对象包含status和value或reason属性,分别表示该 Promise 的状态和值或原因。
那么你可能就会有一个疑问了,为什么我们在 then 就可以执行异步操作失败后的回调函数,那我为什么还需要catch。 这是因为:
虽然 then() 方法可以捕获异步操作失败后的回调函数,但是在实际开发中,有时候我们可能会有一连串的异步操作,而这些操作中的任何一个失败都会导致整个 Promise 链的失败。在这种情况下,如果每个 then() 都添加失败的回调函数,代码会变得冗长和不易维护。
catch() 方法的作用就是用来捕获整个 Promise 链中的任何错误,并统一处理这些错误。通过在 Promise 链的末尾使用 catch() 方法,我们可以避免在每个 then() 中都添加失败的回调函数,从而使代码更加简洁和易读。
另外,使用 catch() 方法还可以避免忘记在每个 then() 后面添加失败回调函数而导致错误被未捕获。因此,即使 then() 中的失败回调函数已经能够捕获错误,使用 catch() 方法也是一种良好的编程习惯,可以提高代码的健壮性和可维护性。
为什么需要Promise
在 JavaScript 中,异步操作经常涉及到网络请求、文件读写、定时器等等。在过去,我们通常使用回调函数来处理异步操作,但回调函数嵌套会导致代码的可读性变差,产生回调地狱的问题。而 Promise 的出现解决了这个问题,使得异步代码的编写更加清晰和易于维护。
它能干什么
Promise 主要用于处理异步操作,例如:
- 发起网络请求并获取响应数据。
- 读取文件或写入文件。
- 执行定时器任务。
- 处理事件监听器等。
Promise 可以让异步操作的流程更加清晰和可控,使得代码结构更加优雅,降低了出错的可能性。
Promise 的优缺点
优点:
- 更清晰的异步流程: Promise 提供了一种清晰的方式来处理异步操作,通过链式调用的方式使得代码更易读、易维护。
- 避免回调地狱: Promise 的链式调用可以避免回调地狱的问题,减少了嵌套层级,使得代码结构更加扁平化。
- 更好的错误处理: Promise 提供了
.catch()方法来统一处理异步操作中的错误,使得错误处理更加方便和一致化。 - 更强大的功能: Promise 还提供了一些其他方法,如
Promise.all()、Promise.race()等,用于处理多个异步操作的情况。
缺点:
- 无法取消 Promise: 一旦创建了 Promise,就无法取消它,这可能会导致内存泄漏。
- 无法得知 Promise 的进度: Promise 只能知道异步操作是成功还是失败,但无法得知其执行的进度,例如完成了多少工作或剩余多少时间。
- 只能处理一次结果: Promise 的状态一经改变就不会再变,一旦成功或失败就无法再次改变,这在某些场景下可能不够灵活。
尽管 Promise 存在一些缺点,但它仍然是 JavaScript 异步编程中的重要解决方案,大大提高了异步代码的可读性、可维护性和可靠性。
结语
以上就是本人对于 Promise 的理解了,对于 Promise 我们还是十分有必要去了解并掌握的,它在日常中的使用是十分频繁的。本人也会在下一篇文章中来为大家讲解一下如何去实现一个高级的 Promise 。