Javascript 是一门异步编程语言。异步编程使得 Javascript 在网络请求、文件读写等场景下表现优异。然而,异步编程也带来了 Callback Hell(回调地狱)和代码可读性差等问题。Promise 就是用来解决这些问题的利器。
什么是 Promise
Promise 是一个代表了异步操作的最终完成或失败的对象。它可以避免 Callback Hell,提高代码的可读性和维护性。Promise 有三种状态:Pending(等待中)、Fulfilled(已完成)和Rejected(已失败)。当 Promise 被创建时,它处于 Pending 状态。当异步操作完成后,Promise 会进入 Fulfilled 状态;如果异步操作失败,则 Promise 进入 Rejected 状态。
Promise 的基本用法
Promise 提供了一个 then 方法,用于在 Promise 进入 Fulfilled 或 Rejected 状态时进行回调处理。then 方法接收两个参数:onFulfilled(成功时回调)和 onRejected(失败时回调)。
例如,下面的代码使用 Promise 发起一个 API 请求,并在请求成功后输出结果,请求失败后输出错误信息。
-- -------------------- ---- ------- -------------------------------- ------------------------ - ------ ---------------- -- -------------------- - ------------------ -- ---------------------- - -------------------- -------- ------- ---展开代码
当 Promise 进入 Fulfilled 状态时,then 方法会返回一个新的 Promise,因此可以链式调用多个 then 方法进行处理。then 方法会将前一个 Promise 返回的值作为参数传递给后一个 Promise。
例如,下面的代码使用 Promise 计算两个数相加的结果,并在计算完成后输出结果。
-- -------------------- ---- ------- -------- ------ -- - ------ --- ------------------------- ------- - --------- - --- --- - ------ -- ------------------- - ------ -------- --- -- ------------------- - ----------------- ---展开代码
Promise 的进阶用法
Promise 还提供了一些进阶用法,例如 all、race 和 finally 方法。
all 方法
Promise.all 方法接收一个 Promise 数组作为参数,返回一个新的 Promise。当所有 Promise 都进入 Fulfilled 状态时,该新的 Promise 进入 Fulfilled 状态,并将所有 Promise 返回的结果以数组形式传递给后续的 then 方法;当其中任意一个 Promise 进入 Rejected 状态时,该新的 Promise 进入 Rejected 状态。
例如,下面的代码使用 Promise.all 方法实现并行调用多个 API,等待所有结果返回后输出结果。
-- -------------------- ---- ------- ------------- --------------------------------------------------------- - ------ ---------------- --- --------------------------------------------------------- - ------ ---------------- -- -- ----------------------- - ----------------------- ------------ -- ---------------------- - -------------------- -------- ------- ---展开代码
race 方法
Promise.race 方法接收一个 Promise 数组作为参数,返回一个新的 Promise。只要有一个 Promise 进入 Fulfilled 或 Rejected 状态,该新的 Promise 就进入相应的状态。它的用途是:Race to finish.
例如,下面的代码使用 Promise.race 方法实现同时发起多个 API 请求,等待任意一个结果返回后输出结果。
-- -------------------- ---- ------- -------------- --------------------------------------------------------- - ------ ---------------- --- --------------------------------------------------------- - ------ ---------------- -- -- ---------------------- - -------------------- -- ---------------------- - -------------------- -------- ------- ---展开代码
finally 方法
Promise.finally 方法接收一个回调函数作为参数,在 Promise 进入 Fulfilled 或 Rejected 状态时均会执行该回调函数。它的作用是进行清理工作或更新 UI 状态。
例如,下面的代码使用 Promise.finally 方法实现在请求完成后隐藏进度条。
-- -------------------- ---- ------- --- ----------- - ---------------------------------------- -------------------------------- ------------------------ - ------ ---------------- -- -------------------- - ------------------ -- ---------------------- - -------------------- -------- ------- -- ------------------- - ------------------------- - ------- ---展开代码
Promise 的错误处理
Promise 的错误处理可以用两种方式实现:使用 catch 方法和在 then 方法中使用第二个参数。
catch 方法
catch 方法用于捕获 Promise 进入 Rejected 状态时抛出的错误,并进行处理。它接收一个回调函数作为参数,该回调函数的参数是错误对象。
例如,下面的代码使用 Promise.catch 方法捕获并输出请求错误信息。
-- -------------------- ---- ------- -------------------------------- ------------------------ - ------ ---------------- -- -------------------- - ------------------ -- ---------------------- - -------------------- -------- ------- ---展开代码
then 方法的第二个参数
then 方法的第二个参数用于处理 Promise 进入 Rejected 状态时抛出的错误。它的作用等同于 catch 方法。
例如,下面的代码使用 Promise.then 方法的第二个参数捕获并输出请求错误信息。
-- -------------------- ---- ------- -------------------------------- ------------------------ - ------ ---------------- -- --------------- - -------------------- -------- ------- -- -------------------- - ------------------ ---展开代码
Promise 的实现
Promise 规范是由 Promises/A+ 组织制订的,任何符合该规范的实现都称为 Promise。在 ES6 中,Promise 已经是内置对象;在 ES5 中,可以通过第三方库实现 Promise,例如 Q 和 Bluebird 等。
下面是一个简单的 Promise 实现,只用于演示用途。
-- -------------------- ---- ------- --- ------- - -- --- --------- - -- --- -------- - -- -------- ----------- - --- ----- - -------- --- ----- - ----- --- -------- - --- -------- --------------- - ----- - ---------- ----- - ------- ------------------------- -------- - ----- - -------- ------------- - ----- - --------- ----- - ------ ------------------------- -------- - ----- - -------- --------------- - --- - --- ---- - ------- ------ --- -------- -- ------ ------ --- ----------- -- ------------ -- ------- ---- --- ----------- - ----------------- -------- -------- ------- - ---------------- - ----- ------- - -------------- - - -------- --------------- - -- ------ --- -------- - ----------------------- - ---- - --- -------- - ----- --- --------- - ------------------- - ------------------- -- --------- --- ----- - -- ------ --- ---------- - ----------------------- - ---- - ---------------------- - - ---- - --- - --- ------ - ---------------- ------------------------ - ----- ------- - ---------------------- - - - - --------- - --------------------- ----------- - ------ --- ------------------------- ------- - -------- ------------ ------------ ----------- ----------- -------- -------- ------- ------ --- --- -- ---------- - -------------------- - ------ --------------- ------------ -- ----------- -------- -展开代码
结论
Promise 是解决 Javascript 异步编程的利器,它可以避免 Callback Hell,提高代码的可读性和维护性。Promise 还提供了一些进阶用法,例如 all、race 和 finally 方法。我们可以使用内置的 Promise 对象,也可以使用第三方库实现 Promise。优秀的前端工程师应该精通 Promise,并在项目中加以应用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/677524ae6d66e0f9aaf42fcd