•
阅读 2 分钟
ES 提案:Promise.try()
由 Jordan Harband 提出的 ES 提案 “Promise.try()” 正处在 stage 1。这篇博客文章解释它怎么样工作。
Promise.try()
为了了解 Promise.try()
是什么,考虑下面的代码:
function countPlusOneAsync() {
return countAsync().then((result) => {
return result + 1
})
}
如果 countAsync()
抛出一个异步异常时,countPlusOneAsync()
同样。但是我们想要的是通过 Promise 传递错误。为了解决这个问题,我们可以使用 Promise.try()
:
function countPlusOneAsync() {
return Promise.try(() => { // (A)
return countAsync() // (B)
}).then((result) => {
return result + 1
})
}
现在行 B 抛出的异常将会被行 A 的 Promise 返回的 rejection 引导。Promise.try()
有两个额外的收益:
- 代码的结构更加一致:所有功能现在都位于回调内部。
- 可以控制使用什么 Promise 实现。无论
countAsync()
返回哪种 thenable,它将转换为Promise
的实例。
替代
在 Promise.try()
还没有提出时,我们可以使用下面的代码变通实现:
function countPlusOneAsync() {
return Promise.resolve()
.then(() => { // (A)
return countAsync()
})
.then((result) => {
return result + 1
})
}
Promise.resolve()
创建一个结果为 undefined
的 Promise。该结果对我们不重要。重要的是我们必须由 Promise 链开始且尝试在开始于行 A 的回调函数中执行代码。
另外一个替代方法是使用 Promise
构造函数:
function countPlusOneAsync() {
return new Promise((resolve) => {
resolve(countAsync())
}).then((result) => {
return result + 1
})
}
FAQ
为什么不仅仅使用 async 函数?
如果可以使用 async 函数,在它的函数体内部转换所有的异常,那将是更好的选择。当然,有时候需要直接使用 Promise 编码,Promise.try()
是有用的。
为什么不只是用 new Promise()
?
Promise.try()
是相对小巧的异步语法糖且很容易填充(polyfill)。与 Promise
构造函数对比,Promise.try()
有下面的优势:
- 在它的回调函数内部的代码与
.then()
回调函数一致,且更容易移除。 - 它更具自我描述性,并且更加简洁。
扩展阅读
- “Exploring ES6” 章节 “Promises for asynchronous programming”
- ES 提案:Promise.prototype.finally
- 在 Promise 回调函数中传递数据
本文由 吳文俊 翻译,原文地址 ES proposal: Promise.try()