假如你对ES6生成器依旧感到陌生,推荐先阅读ES6生成器基础,但是如果你已经准备好了,那现在就来深入了解一下ES6生成器吧。
错误处理
ES6生成器设计中最厉害的一点就是,即使外部迭代控制器的进程是异步的,生成器内部的语义都是同步的。
神奇的是,你可以利用这一点来实现简单的错误处理,可能你对此并不陌生—try…catch机制,比如:
1 2 3 4 5 6 7 8 9 |
function *foo() { try { var x = yield 3; console.log( "x: " + x ); // may never get here! } catch (err) { console.log( "Error: " + err ); } } |
即使上述代码暂停在yield 3这句,如果有error产生并被发送回了生成器,try…catch依然会捕捉到这个错误!你可以尝试用普通的异步方法(比如回调)来实现这个效果:)
但是,到底错误是如何被发送回生成器的呢?
1 2 3 4 5 6 7 |
var it = foo(); var res = it.next(); // { value:3, done:false } // instead of resuming normally with another `next(..)` call, // let's throw a wrench (an error) into the gears: it.throw( "Oops!" ); // Error: Oops! |
你可以看到迭代器里我们使用了一个throw(..)方法,当生成器暂停在某一个yield中时,如果有一个错误在这时候发生了,这个方法就能将错误传给生成器。try…catch捕获错误的方式正如你所想的那样。
注意:如果你只使用了throw(..)尝试将错误传入生成器,但没有使用try…catch捕捉到错误,这个错误将会立马溜走(就像普通流程中的那样,如果没有捕获到错误那最终会变成未处理的拒绝),所以:
1 2 3 4 5 6 7 8 9 |
function *foo() { } var it = foo(); try { it.throw( "Oops!" ); } catch (err) { console.log( "Error: " + err ); // Error: Oops! } |
很明显,将错误处理(error handling)反过来写也是可以的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function *foo() { var x = yield 3; var y = x.toUpperCase(); // could be a TypeError error! yield y; } var it = foo(); it.next(); // { value:3, done:false } try { it.next( 42 ); // `42` won't have `toUpperCase()` } catch (err) { console.log( err ); // TypeError (from `toUpperCase()` call) } |
委托生成器
可能你会想在一个生成器方法中调用别的生成器,在这里我说的并不仅仅是用普通的方式实例化一个生成器,而是将你自己的迭代器委托给其他的生成器。我们可以用yield的变形yield *来实现。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function *foo() { yield 3; yield 4; } function *bar() { yield 1; yield on-line" id="crayon-5812f14fe23a4223691260-7"> yield 1; yield nk">ES6生成器基础,但是如果你已经准备好了,那现在就来深入了解一下ES6生成器吧。
错误处理 ES6生成器设计中最厉害的一点就是,即使外部迭代控制器的进程是异步的,生成器内部的语义都是同步的。 神奇的是,你可以利用这一点来实现简单的错误处理,可能你对此并不陌生—try…catch机制,比如:
即使上述代码暂停在yield 3这句,如果有error产生并被发送回了生成器,try…catch依然会捕捉到这个错误!你可以尝试用普通的异步方法(比如回调)来实现这个效果:) 但是,到底错误是如何被发送回生成器的呢?
你可以看到迭代器里我们使用了一个throw(..)方法,当生成器暂停在某一个yield中时,如果有一个错误在这时候发生了,这个方法就能将错误传给生成器。try…catch捕获错误的方式正如你所想的那样。 注意:如果你只使用了throw(..)尝试将错误传入生成器,但没有使用try…catch捕捉到错误,这个错误将会立马溜走(就像普通流程中的那样,如果没有捕获到错误那最终会变成未处理的拒绝),所以:
很明显,将错误处理(error handling)反过来写也是可以的:
委托生成器 可能你会想在一个生成器方法中调用别的生成器,在这里我说的并不仅仅是用普通的方式实例化一个生成器,而是将你自己的迭代器委托给其他的生成器。我们可以用yield的变形yield *来实现。 例子:
|