前言
前段时间的面试中,发现面试官是经常提出对于 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 。