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:
parent
ff35ad8399
commit
e5b32087c9
118
docs/promise.md
118
docs/promise.md
@ -509,12 +509,12 @@ Promise.all([
|
|||||||
`Promise.race`方法同样是将多个Promise实例,包装成一个新的Promise实例。
|
`Promise.race`方法同样是将多个Promise实例,包装成一个新的Promise实例。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var p = Promise.race([p1,p2,p3]);
|
var p = Promise.race([p1, p2, p3]);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,只要`p1`、`p2`、`p3`之中有一个实例率先改变状态,`p`的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给`p`的回调函数。
|
上面代码中,只要`p1`、`p2`、`p3`之中有一个实例率先改变状态,`p`的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给`p`的回调函数。
|
||||||
|
|
||||||
`Promise.race`方法的参数与`Promise.all`方法一样,如果不是Promise实例,就会先调用下面讲到的`Promise.resolve`方法,将参数转为Promise实例,再进一步处理。
|
`Promise.race`方法的参数与`Promise.all`方法一样,如果不是 Promise 实例,就会先调用下面讲到的`Promise.resolve`方法,将参数转为 Promise 实例,再进一步处理。
|
||||||
|
|
||||||
下面是一个例子,如果指定时间内没有获得结果,就将Promise的状态变为`reject`,否则变为`resolve`。
|
下面是一个例子,如果指定时间内没有获得结果,就将Promise的状态变为`reject`,否则变为`resolve`。
|
||||||
|
|
||||||
@ -768,3 +768,115 @@ run(g);
|
|||||||
|
|
||||||
上面代码的Generator函数`g`之中,有一个异步操作`getFoo`,它返回的就是一个`Promise`对象。函数`run`用来处理这个`Promise`对象,并调用下一个`next`方法。
|
上面代码的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(...)
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -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)
|
- 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 实现观察者模式
|
- 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
|
## Iterator
|
||||||
|
|
||||||
- Mozilla Developer Network, [Iterators and generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)
|
- 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规格的详尽讲解
|
- 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 循环完成预定的操作步骤
|
- 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函数
|
## 异步操作和Async函数
|
||||||
|
|
||||||
- Luke Hoban, [Async Functions for ECMAScript](https://github.com/lukehoban/ecmascript-asyncawait): Async函数的设计思想,与Promise、Gernerator函数的关系
|
- Luke Hoban, [Async Functions for ECMAScript](https://github.com/lukehoban/ecmascript-asyncawait): Async函数的设计思想,与Promise、Gernerator函数的关系
|
||||||
|
Loading…
x
Reference in New Issue
Block a user