1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 10:22:23 +00:00

docs(promise): add Promise.try()

This commit is contained in:
ruanyf 2016-11-30 11:39:40 +08:00
parent ff35ad8399
commit e5b32087c9
2 changed files with 127 additions and 13 deletions

View File

@ -768,3 +768,115 @@ run(g);
上面代码的Generator函数`g`之中,有一个异步操作`getFoo`,它返回的就是一个`Promise`对象。函数`run`用来处理这个`Promise`对象,并调用下一个`next`方法。
## Promise.try()
实际开发中,经常遇到一种情况:不知道函数`f`是同步函数,还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管`f`是否包含异步操作,都用`then`方法指定下一步流程,用`catch`方法处理`f`抛出的错误。一般就会采用下面的写法。
```javascript
Promise.resolve().then(f)
```
上面的写法有一个缺点,就是如果`f`是同步函数,那么它会在下一轮事件循环执行。
```javascript
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
```
上面代码中,函数`f`是同步的,但是用 Promise 包装了以后,就变成异步执行了。
那么有没有一种方法,让同步函数同步执行,异步函数异步执行,并且让它们具有统一的 API 呢?回答是可以的,并且还有两种写法。第一种写法是用`async`函数来写。
```javascript
const f = () => console.log('now');
(async () => f())();
console.log('next');
// now
// next
```
上面代码中,第一行是一个立即执行的匿名函数,会立即执行里面的`async`函数,因此如果`f`是同步的,就会得到同步的结果;如果`f`是异步的,就可以用`then`指定下一步,就像下面的写法。
```javascript
(async () => f())()
.then(...)
```
需要注意的是,`async () => f()`会吃掉`f()`抛出的错误。所以,如果想捕获错误,要使用`promise.catch`方法。
```javascript
(async () => f())()
.then(...)
.catch(...)
```
第二种写法是使用`new Promise()`
```javascript
const f = () => console.log('now');
(
() => new Promise(
resolve => resolve(f())
)
)();
console.log('next');
// now
// next
```
上面代码也是使用立即执行的匿名函数,执行`new Promise()`。这种情况下,同步函数也是同步执行的。
鉴于这是一个很常见的需求,所以现在有一个[提案](https://github.com/ljharb/proposal-promise-try),提供`Promise.try`方法替代上面的写法。
```javascript
const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next
```
事实上,`Promise.try`存在已久Promise 库[`Bluebird`](http://bluebirdjs.com/docs/api/promise.try.html)、[`Q`](https://github.com/kriskowal/q/wiki/API-Reference#promisefcallargs)和[`when`](https://github.com/cujojs/when/blob/master/docs/api.md#whentry),早就提供了这个方法。
由于`Promise.try`为所有操作提供了统一的处理机制,所以如果想用`then`方法管理流程,最好都用`Promise.try`包装一下。这样有[许多好处](http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/),其中一点就是可以更好地管理异常。
```javascript
function getUsername(userId) {
return database.users.get({id: userId})
.then(function(user) {
return uesr.name;
});
}
```
上面代码中,`database.users.get()`返回一个 Promise 对象,如果抛出异步错误,可以用`catch`方法捕获,就像下面这样写。
```javascript
database.users.get({id: userId})
.then(...)
.catch(...)
```
但是`database.users.get()`可能还会抛出同步错误(比如数据库连接错误,具体要看实现方法),这时你就不得不用`try...catch`去捕获。
```javascript
try {
database.users.get({id: userId})
.then(...)
.catch(...)
} catch (e) {
// ...
}
```
上面这样的写法就很笨拙了,这时就可以统一用`promise.catch()`捕获所有同步和异步的错误。
```javascript
Promise.try(database.users.get({id: userId}))
.then(...)
.catch(...)
```

View File

@ -127,6 +127,18 @@
- Axel Rauschmayer, [Pitfall: not all objects can be wrapped transparently by proxies](http://www.2ality.com/2016/11/proxying-builtins.html)
- Bertalan Miklos, [Writing a JavaScript Framework - Data Binding with ES6 Proxies](https://blog.risingstack.com/writing-a-javascript-framework-data-binding-es6-proxy/): 使用 Proxy 实现观察者模式
## Promise对象
- Jake Archibald, [JavaScript Promises: There and back again](http://www.html5rocks.com/en/tutorials/es6/promises/)
- Tilde, [rsvp.js](https://github.com/tildeio/rsvp.js)
- Sandeep Panda, [An Overview of JavaScript Promises](http://www.sitepoint.com/overview-javascript-promises/): ES6 Promise入门介绍
- Dave Atchley, [ES6 Promises](http://www.datchley.name/es6-promises/): Promise的语法介绍
- Axel Rauschmayer, [ECMAScript 6 promises (2/2): the API](http://www.2ality.com/2014/10/es6-promises-api.html): 对ES6 Promise规格和用法的详细介绍
- Jack Franklin, [Embracing Promises in JavaScript](http://javascriptplayground.com/blog/2015/02/promises/): catch 方法的例子
- Ronald Chen, [How to escape Promise Hell](https://medium.com/@pyrolistical/how-to-get-out-of-promise-hell-8c20e0ab0513#.2an1he6vf): 如何使用`Promise.all`方法的一些很好的例子
- Jordan Harband, [proposal-promise-try](https://github.com/ljharb/proposal-promise-try): Promise.try() 方法的提案
- Sven Slootweg, [What is Promise.try, and why does it matter?](http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/): Promise.try() 方法的优点
## Iterator
- Mozilla Developer Network, [Iterators and generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)
@ -154,16 +166,6 @@
- Axel Rauschmayer, [ES6 generators in depth](http://www.2ality.com/2015/03/es6-generators.html): Generator规格的详尽讲解
- Derick Bailey, [Using ES6 Generators To Short-Circuit Hierarchical Data Iteration](https://derickbailey.com/2015/10/05/using-es6-generators-to-short-circuit-hierarchical-data-iteration/):使用 for...of 循环完成预定的操作步骤
## Promise对象
- Jake Archibald, [JavaScript Promises: There and back again](http://www.html5rocks.com/en/tutorials/es6/promises/)
- Tilde, [rsvp.js](https://github.com/tildeio/rsvp.js)
- Sandeep Panda, [An Overview of JavaScript Promises](http://www.sitepoint.com/overview-javascript-promises/): ES6 Promise入门介绍
- Dave Atchley, [ES6 Promises](http://www.datchley.name/es6-promises/): Promise的语法介绍
- Axel Rauschmayer, [ECMAScript 6 promises (2/2): the API](http://www.2ality.com/2014/10/es6-promises-api.html): 对ES6 Promise规格和用法的详细介绍
- Jack Franklin, [Embracing Promises in JavaScript](http://javascriptplayground.com/blog/2015/02/promises/): catch方法的例子
- Ronald Chen, [How to escape Promise Hell](https://medium.com/@pyrolistical/how-to-get-out-of-promise-hell-8c20e0ab0513#.2an1he6vf): 如何使用`Promise.all`方法的一些很好的例子
## 异步操作和Async函数
- Luke Hoban, [Async Functions for ECMAScript](https://github.com/lukehoban/ecmascript-asyncawait): Async函数的设计思想与Promise、Gernerator函数的关系