Skip to content

Commit

Permalink
Update all examples to modern Q usage and style.
Browse files Browse the repository at this point in the history
Also fixed accuracy of the generators readme.
  • Loading branch information
domenic committed Jul 29, 2013
1 parent c842f54 commit 7ac15f3
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 386 deletions.
15 changes: 8 additions & 7 deletions examples/all.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"use strict";

var Q = require("../q");

var eventually = function (eventually) {
return Q.delay(eventually, 1000);
};
function eventually(value) {
return Q.delay(value, 1000);
}

var x = Q.all([1, 2, 3].map(eventually));
Q.when(x, function (x) {
Q.all([1, 2, 3].map(eventually))
.done(function (result) {
console.log(x);
});

Expand All @@ -16,5 +17,5 @@ Q.all([
])
.spread(function (x, y) {
console.log(x, y);
});

})
.done();
44 changes: 18 additions & 26 deletions examples/async-generators/0.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<head>
<title>Q.async animation example</title>
<!--
Works in browsers that support ES6 geneartors, like Chromium 29 with
the --harmony flag.
Expand All @@ -9,36 +10,27 @@
The animation example was taken from
<http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions>
-->
</head>
<body>
<div id="box" style="width: 20px; height: 20px; background-color: red;"></div>

<script src="../../q.js"></script>
<script>
(function () {
"use strict";

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

var deferredAnimate = Q.async(function*(element) {
var deferredAnimate = Q.async(function* (element) {
for (var i = 0; i < 100; ++i) {
element.style.marginLeft = ''+i+'px';
yield delay(20);
element.style.marginLeft = i + "px";
yield Q.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>
Q.spawn(function* () {
yield deferredAnimate(document.getElementById("box"));
alert("Done!");
});
}());
</script>
</body>
</html>
36 changes: 0 additions & 36 deletions examples/async-generators/1-return.html

This file was deleted.

19 changes: 19 additions & 0 deletions examples/async-generators/1-return.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use strict";

var Q = require("../../q");

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

generator().then(function (forty) {
console.log(forty, 40);
}, function (reason) {
console.log("reason", reason);
});
38 changes: 0 additions & 38 deletions examples/async-generators/2-error-propagation.html

This file was deleted.

21 changes: 21 additions & 0 deletions examples/async-generators/2-error-propagation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use strict";

var Q = require("../../q");

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

generator().then(function () {
console.log("Should not get here 2");
}, function (reason) {
console.log("Should get here 2");
console.log(reason.message, "should be", "Threw!");
});
8 changes: 5 additions & 3 deletions examples/async-generators/3-spawn.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
var Q = require('../../q');
"use strict";

var Q = require("../../q");

function foo() {
return Q.delay(5, 1000);
Expand All @@ -8,12 +10,12 @@ function bar() {
return Q.delay(10, 1000);
}

Q.spawn(function*() {
Q.spawn(function* () {
var x = yield foo();
console.log(x);

var y = yield bar();
console.log(y);

console.log('result', x + y);
console.log("result", x + y);
});
38 changes: 20 additions & 18 deletions examples/async-generators/4-flow-control.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
var Q = require('../../q');
"use strict";

// we get back blocking semantics - can use promises
// with if, while, for etc
var filter = Q.async(function*(promises,test) {
var Q = require("../../q");

// We get back blocking semantics: can use promises with `if`, `while`, `for`,
// etc.
var filter = Q.async(function* (promises, test) {
var results = [];
for(var i = 0; i < promises.length; i++) {
for (var i = 0; i < promises.length; i++) {
var val = yield promises[i];
if(test(val)) results.push(val);
if (test(val)) {
results.push(val);
}
}
return results;
});

var alreadyResolved = Q;
var promises = [
Q.delay("a",500),
Q.delay("d",1000),
alreadyResolved("l")
Q.delay("a", 500),
Q.delay("d", 1000),
Q("l")
];

filter(promises,function(letter) {
filter(promises, function (letter) {
return "f" > letter;
}).done(function(all) {
}).done(function (all) {
console.log(all); // [ "a", "d" ]
});


// we can use try and catch to handle rejected promises
var logRejections = Q.async(function*(work) {
var logRejections = Q.async(function* (work) {
try {
yield work;
console.log("Never end up here");
} catch(e) {
console.log("Caught:",e);
} catch (e) {
console.log("Caught:", e.message);
}
});

var reject = Q.defer();
reject.reject("Oh dear");
logRejections(reject.promise); // Caught: Oh dear
var rejection = Q.reject(new Error("Oh dear"));
logRejections(rejection); // Caught: Oh dear
63 changes: 27 additions & 36 deletions examples/async-generators/README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
/!\ Warning: The behavior described here is likely to be quickly
obseleted by developments in standardization and implementation. Tread
with care.
/!\ Warning: The behavior described here is likely to be quickly obseleted by
developments in standardization and implementation. Tread with care.

Q has an ``async`` function. This can be used to
decorate a generator function such that ``yield`` is
effectively equivalent to ``await`` or ``defer`` syntax as
Q has an `async` function. This can be used to decorate a generator function
such that `yield` is effectively equivalent to `await` or `defer` syntax as
supported by languages like Go and C# 5.

Generator functions are presently on the standards track for ES6. As of
May 2013, they are only fully supported by bleeding edge V8, which
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.
Generator functions are presently on the standards track for ES6. As of July
2013, they are only fully supported by bleeding edge V8, which hasn't made it
out to a released Chromium yet but will probably be in Chromium 29. Even then,
they must be enabled from [chrome://flags](chrome://flags) as "Experimental
JavaScript features." SpiderMonkey (used in Firefox) includes an older style of
generators, but these are not supported by Q.

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.
Here's an example of using generators by themselves, without any Q features:

```js
function* count() {
Expand All @@ -28,13 +23,13 @@ function* count() {
}

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

``yield`` can also return a value, if the ``send`` method of
a generator is used instead of ``next``.
`yield` can also return a value, if the `next` method of the generator is
called with a parameter:

```js
var buffer = (function* () {
Expand All @@ -44,15 +39,16 @@ var buffer = (function* () {
}
}());

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

We can use ``yield`` to wait for a promise to resolve.
Inside functions wrapped with `Q.async`, we can use `yield` to wait for a
promise to settle:

```js
var eventualAdd = Q.async(function* (oneP, twoP) {
Expand All @@ -61,14 +57,9 @@ var eventualAdd = Q.async(function* (oneP, twoP) {
return one + two;
});

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

To use these in SpiderMonkey, change ``function*`` to ``function``.
Also, in this last example, SpiderMonkey does not allow return values in
generators. To work around that, call the ``Q.return`` function instead
of using a ``return`` statement. ``Q.return`` will go away at some
point when SpiderMonkey switches to ES6 style.
You can see more examples of how this works, as well as the `Q.spawn` function,
in the other files in this folder.
Loading

0 comments on commit 7ac15f3

Please sign in to comment.