什么是 Promise?
Promise 是 ES6 提供的一种解决异步编程的方案,它可以让我们更优雅、更简洁的处理回调函数地狱,特别是在处理非常多的异步请求时,可以极大地提高代码的可维护性。
Promise 有三种状态,分别是 pending
(等待中)、fulfilled
(完成)和 rejected
(失败)。当 Promise 的状态从 pending
转换为 fulfilled
或 rejected
时,就称为 Promise 已经 resolve(resolved)。
Promise 的用法
使用 Promise 很简单,只需要实例化 Promise 对象,将异步任务放在 Promise 的回调函数中,返回 Promise 对象给调用方,调用方再通过链式调用 then() 和 catch() 方法来处理异步任务的结果就可以了。具体代码如下:
-- -------------------- ---- ------- ----- ------- - --- ----------------- ------- -- - ------------- -- - ----- ---- - ------- ---------- -------------- -- --------- -- ----------------- -- ----------- -- ------ --- ------- ---------- -- - ------------------ -- ------- --------- -- ------------ -- - ------------------- -- -------- ---
代码中,我们用 setTimeout 模拟了一个异步任务,当两秒后返回数据。我们使用 Promise 实例化一个 Promise 对象,将异步任务放在 Promise 的回调函数中。resolve
函数用于返回数据,reject
用于返回错误信息。最后,我们将 Promise 对象返回给调用方,并通过链式调用 then() 和 catch() 方法来处理异步任务的结果。
Promise 的方法
Promise 除了 then() 和 catch() 方法之外,还提供了一些其他的方法。
Promise.all()
Promise.all() 方法用于将多个 Promise 对象封装成一个Promise,等到每个 Promise 都 resolve 后,then() 方法才会被执行,结果会按照 Promise 数组顺序返回结果。当其中任意一个 Promise 返回 reject,就立即返回 reject,并终止执行。具体代码如下:
const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); const promise3 = Promise.resolve(3); Promise.all([promise1, promise2, promise3]) .then(results => console.log(results)) // [1, 2, 3] .catch(error => console.log(error)); // 不会执行
Promise.race()
Promise.race() 方法用于将多个 Promise 对象封装成一个 Promise,只要有一个 Promise resolve 或 reject ,就会执行 then() 方法或 catch() 方法,结果将会按照该 Promise 的顺序返回,并对后续结果进行忽略。具体代码如下:
const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 1000)); const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 2000)); const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 3000)); Promise.race([promise1, promise2, promise3]) .then(result => console.log(result)) // 1
Promise.resolve()
Promise.resolve() 方法用于将现有对象转换成 Promise 对象,如果传入的是 Promise 对象,则返回它本身。具体代码如下:
Promise.resolve(123) // 等价于 return new Promise(resolve => resolve(123)) .then(result => console.log(result)); // 123
Promise.reject()
Promise.reject() 方法用于将现有对象转换成 Promise 对象,状态为 rejected。具体代码如下:
Promise.reject('Error!') .catch(error => console.log(error)); // 'Error!'
Promise 的错误处理
在使用 Promise 的过程中,异常处理是必不可少的一部分。我们可以使用 catch() 方法捕获异常,也可以使用 then() 方法中的第二个回调函数来处理异常。具体代码如下:
-- -------------------- ---- ------- ----- ------- - --- ----------------- ------- -- - ------------- -- - ---------- ----------------- -- ------ --- ------- ------------ -- -------------------- ------------ -- -------------------- -- ------
Promise catch() 方法可以捕获 reject() 中抛出的错误,并将其传递到回调函数中。当如上面的例子,当 Promise 实例化后,通过回调函数传递一个 Error 对象给 reject() 函数。
我们在 then() 方法中使用了第二个回调函数来处理异常,并将 Error 对象传递给它。在这种情况下,第一个回调函数将会被跳过,而是执行 catch() 方法中的回调函数。
Promise 的扩展
Promise 的作用不仅仅局限于单一的异步操作,还能通过 Promise.all() 方法来封装多个异步操作为一个 Promise 对象。除此之外,我们还可以使用 Promise 来实现其它的功能。
以下是一个使用 Promise 实现的图片预加载器示例,具体代码如下:
-- -------------------- ---- ------- --- ------------ - ------ -- - ------ --- ----------------- ------- -- - --- ----- - --- -------- ------------ - -- -- - --------------- -- ------------- - -- -- - ---------- ------------ --- ---- ----- ---- ----------- -- --------- - ----- --- -- ------------- ---------------------------------------------- ---------------------------------------------- -- --------------- -------- -- - ---------------------------------- ---------------------------------- -- ------------ -- --------------------
以上代码,通过 Promise.all() 方法实现了两个图片预加载任务的封装。Promise.all() 方法将两个 Promise 任务封装到一个 Promise 对象中,等待两个异步任务完成后,调用 Promise 对象的 then() 方法来添加元素。
总结
本文介绍了 Promise 的基本用法、方法、错误处理和扩展。Promise 的出现,使得我们在异步编程的时候,可以更简洁、优美的处理回调函数的问题,降低了代码的复杂性,提高了代码的可维护性。
同时,我们还通过 Promise.all() 方法和 Promise.race() 方法实现了多个异步任务的并行执行和竞态执行,并通过 Promise.resolve() 方法和 Promise.reject() 方法将现有对象转换成 Promise 对象。
在现实应用中,我们也可以使用 Promise 封装自己的异步任务,使其更加易于控制和维护。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/646dcd7d968c7c53b0c6dbd1