前言
在 JavaScript 中,异步操作是一个不可避免的话题。Promise 就是一种用于处理异步操作的技术,它的出现使得异步操作变得更加容易管理和组织。本文将深入探讨 Promise 的原理和用法,并介绍 Promise 在 ES6/ES7/ES8/ES9 中的演变,帮助读者更好地掌握 Promise 技术。
Promise 原理
Promise 是一种封装异步操作的对象,它可以让我们更方便地处理异步任务的结果。Promise 的基本结构如下:
-- -------------------- ---- ------- --- ----------------- ------- -- - -- ---- -- ------------ -- - -- ------ -- ------------ -- - -- ---- ---
在 Promise 中,我们可以通过 resolve
和 reject
方法来处理异步任务的结果。resolve
方法用于处理成功的情况,reject
方法用于处理失败的情况。当异步任务完成后,我们可以通过 then
方法来处理成功的结果,通过 catch
方法来处理失败的结果。
下面是一个使用 Promise 处理异步任务的示例代码:
-- -------------------- ---- ------- --- ----------------- ------- -- - ------------- -- - ----- ------ - ------------- - ---- -- -------- - ------------------- - ---- - ---------- ------------------ - -- ------ -- ------------ -- - -------------------- -- ------------ -- - --------------------- ---
在上面的代码中,我们创建了一个 Promise 对象,并在其中执行了一个异步任务。在异步任务完成后,我们使用 resolve
或 reject
方法来处理结果。然后,在 then
方法中处理成功的结果,在 catch
方法中处理失败的结果。
ES6 中的 Promise
在 ES6 中,Promise 得到了原生支持,我们可以直接使用 Promise 对象来处理异步任务。在 ES6 中,Promise 的基本用法和原理没有变化,但是引入了一些新的语法糖,使得 Promise 更加易用和灵活。
Promise.all
Promise.all
方法可以用于处理多个异步任务,并在所有任务完成后一起处理结果。它接受一个包含多个 Promise 对象的数组作为参数,返回一个新的 Promise 对象。当所有的 Promise 对象都成功执行后,Promise.all
方法返回的 Promise 对象将会被 resolved,它的结果是一个包含所有成功结果的数组。如果有任何一个 Promise 对象失败了,Promise.all
方法返回的 Promise 对象将会被 rejected,它的结果是失败的 Promise 对象的错误信息。
下面是一个使用 Promise.all
处理多个异步任务的示例代码:
-- -------------------- ---- ------- ----- -------- - --- ----------------- ------- -- - ------------- -- - ------------------- -- ------ --- ----- -------- - --- ----------------- ------- -- - ------------- -- - ------------------- -- ------ --- ---------------------- ---------- ------------- -- - --------------------- -- ------------ -- - --------------------- ---
在上面的代码中,我们创建了两个 Promise 对象,然后使用 Promise.all
方法来处理它们。在所有 Promise 对象都成功执行后,then
方法会被调用,它的结果是一个包含所有成功结果的数组。
Promise.race
Promise.race
方法可以用于处理多个异步任务,并在其中任何一个任务完成后处理结果。它接受一个包含多个 Promise 对象的数组作为参数,返回一个新的 Promise 对象。当任何一个 Promise 对象成功执行后,Promise.race
方法返回的 Promise 对象将会被 resolved,它的结果是第一个成功结果。如果有任何一个 Promise 对象失败了,Promise.race
方法返回的 Promise 对象将会被 rejected,它的结果是失败的 Promise 对象的错误信息。
下面是一个使用 Promise.race
处理多个异步任务的示例代码:
-- -------------------- ---- ------- ----- -------- - --- ----------------- ------- -- - ------------- -- - ------------------- -- ------ --- ----- -------- - --- ----------------- ------- -- - ------------- -- - ------------------- -- ------ --- ----------------------- ---------- ------------ -- - -------------------- -- ------------ -- - --------------------- ---
在上面的代码中,我们创建了两个 Promise 对象,然后使用 Promise.race
方法来处理它们。当任何一个 Promise 对象成功执行后,then
方法会被调用,它的结果是第一个成功结果。
ES7 中的 Async/Await
在 ES7 中,引入了 async
和 await
两个关键字,使得异步任务的处理更加简单和直观。async
和 await
可以让我们以同步的方式编写异步代码,使用起来非常方便。
async
async
关键字用于声明一个异步函数,它返回一个 Promise 对象。在异步函数中,我们可以使用 await
关键字来等待异步任务的完成,并处理任务的结果。
下面是一个使用 async
声明异步函数的示例代码:
-- -------------------- ---- ------- ----- -------- ----------- - ----- -------- - ----- -------------------------------------- ----- ---- - ----- ---------------- ------ ----- - ----------- ---------- -- - ------------------ -- ------------ -- - --------------------- ---
在上面的代码中,我们使用 async
关键字声明了一个异步函数 fetchData
,它返回一个 Promise 对象。在函数中,我们使用 await
关键字等待异步任务的完成,并处理任务的结果。最后,我们通过 then
方法处理异步任务的结果。
await
await
关键字用于等待异步任务的完成,并处理任务的结果。在异步函数中,我们可以使用 await
关键字来等待异步任务的完成,并将结果存储在变量中,然后使用这个变量来处理任务的结果。
下面是一个使用 await
等待异步任务的完成的示例代码:
-- -------------------- ---- ------- ----- -------- ----------- - ----- -------- - ----- -------------------------------------- ----- ---- - ----- ---------------- ------ ----- - ----------- ---------- -- - ------------------ -- ------------ -- - --------------------- ---
在上面的代码中,我们使用 await
关键字等待异步任务的完成,并将结果存储在变量中。然后,我们使用这个变量来处理任务的结果。
ES8 中的 async/await 更多特性
在 ES8 中,async/await
还引入了一些新的特性,使得异步代码的编写更加灵活和方便。
Async Iteration
Async Iteration
允许我们使用 for await...of
循环遍历异步任务的结果。在异步函数中,我们可以使用 yield
关键字返回一个 Promise 对象,然后在 for await...of
循环中使用 await
关键字等待 Promise 对象的完成,并处理任务的结果。
下面是一个使用 for await...of
循环遍历异步任务的结果的示例代码:
-- -------------------- ---- ------- ----- -------- ----------- - ----- -------- - ----- -------------------------------------- ----- ------ - -------------------------- ----- ------ - ----- - ----- ----- - - ----- -------------- -- ------ - ------ - ------------------- - - ----------- ------------ -- - --------------------- ---
在上面的代码中,我们使用 fetch
方法获取数据,并将结果存储在 response
变量中。然后,我们使用 response.body.getReader()
方法获取一个可读流,并使用 while
循环遍历流中的数据。在循环中,我们使用 await
关键字等待数据的到达,并处理数据的结果。
Promise.prototype.finally
Promise.prototype.finally
方法可以在 Promise 对象完成后执行一个回调函数。它接受一个回调函数作为参数,并返回一个新的 Promise 对象。当原始的 Promise 对象完成后,无论它的结果是 resolved 还是 rejected,finally
方法都会被调用。
下面是一个使用 Promise.prototype.finally
方法的示例代码:
-- -------------------- ---- ------- --- ----------------- ------- -- - ------------- -- - ----- ------ - ------------- - ---- -- -------- - ------------------- - ---- - ---------- ------------------ - -- ------ -- ------------ -- - -------------------- -- ------------ -- - --------------------- -- ----------- -- - ----------------------- ---
在上面的代码中,我们创建了一个 Promise 对象,并在其中执行了一个异步任务。在异步任务完成后,我们使用 then
或 catch
方法处理结果。然后,在 finally
方法中处理任务完成后的逻辑。
ES9 中的 Promise.prototype.finally
在 ES9 中,Promise.prototype.finally
方法得到了原生支持,我们可以直接使用它来处理异步任务的结果。在 ES9 中,Promise.prototype.finally
方法的用法和原理与 ES8 中相同,但是它已经成为了原生的 API。
下面是一个使用 ES9 中的 Promise.prototype.finally
方法的示例代码:
-- -------------------- ---- ------- --- ----------------- ------- -- - ------------- -- - ----- ------ - ------------- - ---- -- -------- - ------------------- - ---- - ---------- ------------------ - -- ------ -- ------------ -- - -------------------- -- ------------ -- - --------------------- -- ----------- -- - ----------------------- ---
在上面的代码中,我们创建了一个 Promise 对象,并在其中执行了一个异步任务。在异步任务完成后,我们使用 then
或 catch
方法处理结果。然后,在 finally
方法中处理任务完成后的逻辑。
总结
在本文中,我们深入探讨了 Promise 的原理和用法,并介绍了 Promise 在 ES6/ES7/ES8/ES9 中的演变。通过学习本文,读者可以更好地掌握 Promise 技术,并在实际开发中灵活应用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6618bf38d10417a2229166c8