Is your goal to wrap a generator, as it seems you are propagating the exception
of the caller by calling iterator.throw(). However, you do not seem to be
propagating the sent value, so the protocol here isn’t fully implmeneted.
If you just want to iterate values (and don’t really care about the return
value of the iterable or propagating a thrown exception, you could write:
```js
function* take(n, iterable) {
n |= 0;
if (n <= 0) {
return;
}
// let for..of call return()
for (let value of iterable) {
yield value;
if (n-- <= 0) {
return;
}
}
}
```
If you want to support the full communication channel of a generator, you could
write:
```js
function* take(n, iterable) {
let iterator = iterable[Symbol.iterator]();
let step = () => iterator.next();
n |= 0;
// try..finally outside of loop
try {
let sent;
while (n > 0) {
let { value, done } = step();
if (done) {
return value;
}
n--;
// try..catch local to the yield
try {
sent = yield value;
step = () => iterator.next(sent);
}
catch (e) {
if (typeof iterator.throw === "function") {
step = () => iterator.throw(e);
}
else {
throw e;
}
}
}
}
finally {
if (typeof iterator.return === "function") {
iterator.return();
}
}
}
```
From: es-discuss [mailto:[email protected]] On Behalf Of Axel
Rauschmayer
Sent: Tuesday, March 24, 2015 2:28 PM
To: Bergi
Cc: es-discuss list
Subject: Re: Forwarding `return()` in generators
Right, it doesn’t look like one needs to know the returned value when
forwarding `return()`.
But: you need to guard against other ways of reaching `finally`. Maybe like
this:
```js
function* take(n, iterable) {
let iterator = iterable[Symbol.iterator]();
n = +n; // make sure it's a number, so that n>0 does never throw
let forwardReturn = true;
try {
while (n > 0) {
let item = iterator.next();
if (item.done) {
forwardReturn = false;
return item.value;
}
yield item.value;
n--;
}
forwardReturn = false;
} catch (e) {
forwardReturn = false;
iterator.throw(e);
} finally {
if (forwardReturn) {
iterator.return();
}
}
}
```
The above code also has the additional nice property that it call `.return()`
on the iterator when `n` values have been taken out of it.
That’s not what all the other constructs in ES6 do: they only call `return()`
if iteration stops abruptly.
Also missing from this code: checking whether the iterator actually has the
methods `return()` and `throw()` and responding accordingly.
--
Dr. Axel Rauschmayer
[email protected]<mailto:[email protected]>
rauschma.de
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss