Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Q.async to work with current ES6 generators #288

Merged
merged 1 commit into from May 8, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 5 additions & 4 deletions examples/async-generators/0.html
Expand Up @@ -2,14 +2,15 @@
<html> <html>
<head> <head>
<!-- <!--
Works in Firefox, or where generators are implemented. Works in browsers that support ES6 geneartors, like Chromium 29 with
the --harmony flag.


Peter Hallam, Tom van Cutsem, Mark S. Miller, Dave Herman. Peter Hallam, Tom van Cutsem, Mark S. Miller, Dave Herman, Andy Wingo.
The animation example was taken from The animation example was taken from
<http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions> <http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions>
--> -->
<script src="../../q.js"></script> <script src="../../q.js"></script>
<script type="application/javascript;version=1.7"> <script>


function delay(millis, answer) { function delay(millis, answer) {
const deferredResult = Q.defer(); const deferredResult = Q.defer();
Expand All @@ -19,7 +20,7 @@
return deferredResult.promise; return deferredResult.promise;
} }


var deferredAnimate = Q.async(function(element) { var deferredAnimate = Q.async(function*(element) {
for (var i = 0; i < 100; ++i) { for (var i = 0; i < 100; ++i) {
element.style.marginLeft = ''+i+'px'; element.style.marginLeft = ''+i+'px';
yield delay(20); yield delay(20);
Expand Down
10 changes: 5 additions & 5 deletions examples/async-generators/1-return.html
Expand Up @@ -2,22 +2,22 @@
<html> <html>
<head> <head>
<!-- <!--
Works in Firefox, or where generators are implemented. Works in browsers that support ES6 geneartors, like Chromium 29 with
the --harmony flag.
--> -->
<script src="../../q.js"></script> <script src="../../q.js"></script>
<script type="application/javascript;version=1.7"> <script>


function test() { function test() {


var generator = Q.async(function () { var generator = Q.async(function* () {
var ten = yield 10; var ten = yield 10;
console.log(ten, 10); console.log(ten, 10);
var twenty = yield ten + 10; var twenty = yield ten + 10;
console.log(twenty, 20); console.log(twenty, 20);
var thirty = yield twenty + 10; var thirty = yield twenty + 10;
console.log(thirty, 30); console.log(thirty, 30);
StopIteration.value = thirty + 10; return thirty + 10;
throw StopIteration;
}); });


Q.when(generator(), function (forty) { Q.when(generator(), function (forty) {
Expand Down
7 changes: 4 additions & 3 deletions examples/async-generators/2-error-propagation.html
Expand Up @@ -2,14 +2,15 @@
<html> <html>
<head> <head>
<!-- <!--
Works in Firefox, or where generators are implemented. Works in browsers that support ES6 geneartors, like Chromium 29 with
the --harmony flag.
--> -->
<script src="../../q.js"></script> <script src="../../q.js"></script>
<script type="application/javascript;version=1.7"> <script>


function test() { function test() {


var generator = Q.async(function () { var generator = Q.async(function* () {
try { try {
var ten = yield Q.reject('Rejected!'); var ten = yield Q.reject('Rejected!');
console.log("Should not get here 1"); console.log("Should not get here 1");
Expand Down
35 changes: 19 additions & 16 deletions examples/async-generators/README.md
Expand Up @@ -8,11 +8,19 @@ decorate a generator function such that ``yield`` is
effectively equivalent to ``await`` or ``defer`` syntax as effectively equivalent to ``await`` or ``defer`` syntax as
supported by languages like Go and, reportedly, C#3. supported by languages like Go and, reportedly, C#3.


Generator functions are presently only supported by SpiderMonkey, but Generator functions are presently on the standards track for ES6. As of
they are (with some changes) on standards track, and very similar down May 2013, they are only fully supported by bleeding edge V8, which
to details to generators in Python. hasn't made it out to a released Chromium yet but will probably be in
Chromium 29. Generators have been in SpiderMonkey for years, but in an
older pre-standard form based on Python's design. The Traceur
transpiler also still uses Python-style generators, which were part of
an older ES6 draft.


function count() { Q's ``async`` function supports both kinds of generators. These
examples will use the ES6 style. See the examples and notes in
[js-1.7](js-1.7/) for more on getting these to work with SpiderMonkey.

function* count() {
var i = 0; var i = 0;
while (true) { while (true) {
yield i++; yield i++;
Expand All @@ -27,7 +35,7 @@ to details to generators in Python.
``yield`` can also return a value, if the ``send`` method of ``yield`` can also return a value, if the ``send`` method of
a generator is used instead of ``next``. a generator is used instead of ``next``.


var buffer = (function () { var buffer = (function* () {
var x; var x;
while (true) { while (true) {
x = yield x; x = yield x;
Expand All @@ -43,7 +51,7 @@ a generator is used instead of ``next``.


We can use ``yield`` to wait for a promise to resolve. We can use ``yield`` to wait for a promise to resolve.


var eventualAdd = Q.async(function (oneP, twoP) { var eventualAdd = Q.async(function* (oneP, twoP) {
var one = yield oneP; var one = yield oneP;
var two = yield twoP; var two = yield twoP;
return one + two; return one + two;
Expand All @@ -54,13 +62,8 @@ We can use ``yield`` to wait for a promise to resolve.
three === 3; three === 3;
}); });


Or, at least we could. For now, SpiderMonkey does not allow To use these in SpiderMonkey, change ``function`` to ``function*``.
return values in generators. When they do, ``Q.async`` will Also, in this last example, SpiderMonkey does not allow return values in
properly fulfill the result of eventualAdd. Until then, generators. To work around that, call the ``Q.return`` function instead
``eventualAdd`` will resolve to ``undefined`` when the job of using a ``return`` statement. ``Q.return`` will go away at some
is done, when the generator throws ``StopIteration``. point when SpiderMonkey switches to ES6 style.

As a stop-gap, you can fake the return value by tacking a
``value`` property on an explicitly thrown
``StopIteration``, as in Example 1, in this directory.

43 changes: 43 additions & 0 deletions examples/async-generators/js-1.7/0.html
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<!--
Works in Firefox, or where generators are implemented.

Peter Hallam, Tom van Cutsem, Mark S. Miller, Dave Herman.
The animation example was taken from
<http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions>
-->
<script src="../../../q.js"></script>
<script type="application/javascript;version=1.7">

function delay(millis, answer) {
const deferredResult = Q.defer();
setTimeout(function() {
deferredResult.resolve(answer);
}, millis);
return deferredResult.promise;
}

var deferredAnimate = Q.async(function(element) {
for (var i = 0; i < 100; ++i) {
element.style.marginLeft = ''+i+'px';
yield delay(20);
}
});

function test() {
Q.when(
deferredAnimate(document.getElementById('box')),
function () {
alert('Done!');
}
)
}

</script>
</head>
<body onload="test()">
<div id="box" style="width: 20px; height: 20px; background-color: red;"></div>
</body>
</html>
Expand Up @@ -2,25 +2,25 @@
<html> <html>
<head> <head>
<!-- <!--
Ought to work in ES.next, if return sugar for Works in Firefox, or where generators are implemented.
generators gets added.
--> -->
<script src="../../q.js"></script> <script src="../../../q.js"></script>
<script type="application/javascript;version=1.7"> <script type="application/javascript;version=1.7">


function test() { function test() {


var eventuallyFourty = Q.async(function () { var generator = Q.async(function () {
var ten = yield 10; var ten = yield 10;
console.log(ten, 10); console.log(ten, 10);
var twenty = yield ten + 10; var twenty = yield ten + 10;
console.log(twenty, 20); console.log(twenty, 20);
var thirty = yield twenty + 10; var thirty = yield twenty + 10;
console.log(thirty, 30); console.log(thirty, 30);
return thrity + 10; StopIteration.value = thirty + 10;
throw StopIteration;
}); });


Q.when(eventuallyFourty(), function (forty) { Q.when(generator(), function (forty) {
console.log(forty, 40); console.log(forty, 40);
}, function (reason) { }, function (reason) {
console.log("error", reason); console.log("error", reason);
Expand Down
37 changes: 37 additions & 0 deletions examples/async-generators/js-1.7/2-error-propagation.html
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<!--
Works in Firefox, or where generators are implemented.
-->
<script src="../../../q.js"></script>
<script type="application/javascript;version=1.7">

function test() {

var generator = Q.async(function () {
try {
var ten = yield Q.reject('Rejected!');
console.log("Should not get here 1");
} catch (exception) {
console.log("Should get here 1");
console.log(exception, "should be", "Rejected!");
throw "Threw!";
}
});

Q.when(generator(), function () {
console.log("Should not get here 2");
}, function (reason) {
console.log("Should get here 2");
console.log(reason, "should be", "Threw!");
});

}

</script>
</head>
<body onload="test()">
<div id="box" style="width: 20px; height: 20px; background-color: red;"></div>
</body>
</html>
Expand Up @@ -4,7 +4,7 @@
<!-- <!--
Works in Firefox, or where generators are implemented. Works in Firefox, or where generators are implemented.
--> -->
<script src="../../q.js"></script> <script src="../../../q.js"></script>
<script type="application/javascript;version=1.7"> <script type="application/javascript;version=1.7">


function test() { function test() {
Expand Down
57 changes: 57 additions & 0 deletions examples/async-generators/js-1.7/README.md
@@ -0,0 +1,57 @@

/!\ Warning: The behavior described here corresponds to a dead-end fork
of JavaScript used in FireFox. If you can, use ES6-style generators,
described [in the parent directory](../). Currently Q works with both
kinds of generators, but perhaps in a year or so, support for the older
SpiderMonkey generators will go away.

Examples of SpiderMonkey-style generators:

function count() {
var i = 0;
while (true) {
yield i++;
}
}

var counter = count();
count.next() === 0;
count.next() === 1;
count.next() === 2;

In this case it's just like ES6 generators, but with ``function``
instead of ``function*``. Like ES6 generators, ``yield`` can also
return a value, if the ``send`` method of a generator is used instead of
``next``:

var buffer = (function () {
var x;
while (true) {
x = yield x;
}
}());

buffer.send(1) === undefined
buffer.send("a") === 1
buffer.send(2) === "a"
buffer.next() === 2
buffer.next() === undefined
buffer.next() === undefined

We can use ``yield`` to wait for a promise to resolve.

var eventualAdd = Q.async(function (oneP, twoP) {
var one = yield oneP;
var two = yield twoP;
Q.return(one + two);
});

eventualAdd(eventualOne, eventualTwo)
.then(function (three) {
three === 3;
});

Note! SpiderMonkey does not allow return values in generators. To work
around that, call the ``Q.return`` function, as used above, instead of
using a ``return`` statement. ``Q.return`` will go away at some point
when SpiderMonkey switches to ES6 style.