Permalink
Browse files

* Initial commit and first npm release.

  • Loading branch information...
0 parents commit a12b950bee26ae13452036d7a502cafea21d0582 @audreyt committed Jun 10, 2012
Showing with 252 additions and 0 deletions.
  1. +11 −0 Makefile
  2. +56 −0 README.md
  3. +19 −0 example.js
  4. +22 −0 package.json
  5. +81 −0 q-jscex.js
  6. +15 −0 src/example.ls
  7. +48 −0 src/q-jscex.ls
@@ -0,0 +1,11 @@
+all :: deps
+ env PATH="$$PATH:./node_modules/LiveScript/bin" livescript -c -o . src
+
+deps ::
+ npm i
+
+demo ::
+ node example.js
+
+test :: all demo
+
@@ -0,0 +1,56 @@
+jscex-jquery
+============
+
+# Synopsis
+
+```javascript
+// Drop-in replacement to require('q')
+var Q = require('q-jscex');
+var HTTP = require('q-http');
+
+// Define an Async function with a special $await keyword in it
+var fetch = eval(Q.async.$(function(url) {
+ // $await takes anything that returns a Q Promise
+ var buf = $await( HTTP.read(url) );
+ // ...pauses one second...
+ $await( Q.delay(1000) );
+ // ...do something with the returned buffer...
+ return buf;
+}));
+
+// Return value of Async functions is always a Q Promise
+fetch('http://.../').done(...).fail(...).fin(...);
+```
+
+# Description
+
+This module exports a Q root object (`Q`) containing an
+`Q.async.$` helper; it compiles a regular function into one
+that returns a Q Promise object.
+
+Functions defined with `Q.async.$` has access to an extra `$await`
+keyword, which implicitly waits for other Q Promise objects.
+
+Please see `example.js` for a sample usage, and type `make demo`
+to see it in action.
+
+The source code is in `src` directory and written in LiveScript.
+Note that LiveScript is _not_ a runtime dependency of this module;
+it's only used for development.
+
+The underlying JIT compiler is available as the `Q.async.$.Jscex` object.
+
+# See Also
+
+* Jscex: http://jscex.info/
+* Q: https://github.com/kriskowal/q
+* LiveScript: https://gkz.github.com/LiveScript
+
+# CC0 1.0 Universal
+
+To the extent possible under law, 唐鳳 has waived all copyright
+and related or neighboring rights to q-jscex.
+
+This work is published from Taiwan.
+
+http://creativecommons.org/publicdomain/zero/1.0
@@ -0,0 +1,19 @@
+(function(){
+ var Q, HTTP, say, fetch;
+ Q = require('./q-jscex');
+ HTTP = require('q-http');
+ say = function(it){
+ console.log(it);
+ console.log('');
+ };
+ fetch = eval(Q.async.$(function(url){
+ var html;
+ html = $await(HTTP.read(url));
+ return html.toString('utf-8', 555, 600);
+ }));
+ say('[Demo: Fetching invalid host, expecting ENOENT...]');
+ fetch('http://blog.zhaojie.error').fail(say).fin(function(){
+ say('[Demo: Fetching valid host, expecting snippet...]');
+ return fetch('http://blog.zhaojie.me').then(say);
+ });
+}).call(this);
@@ -0,0 +1,22 @@
+{ "name" : "q-jscex"
+ , "description" : "Async/Await syntax support for Q promises"
+ , "version" : "0.0.1"
+ , "main": "q-jscex.js"
+ , "dependencies": {
+ "q": "*",
+ "jscex": "*",
+ "jscex-jit": "*",
+ "jscex-async": "*"
+ }
+ , "devDependencies": {
+ "LiveScript": "0.9.7",
+ "q-http": "*"
+ }
+ , "keywords": ["control-flow", "promise", "q", "async", "jit", "await"]
+ , "homepage": "https://github.com/audreyt/q-jscex"
+ , "author": "唐鳳 <audreyt@audreyt.org>"
+ , "repository": {
+ "type": "git",
+ "url": "https://github.com/audreyt/q-jscex.git"
+ }
+}
@@ -0,0 +1,81 @@
+(function(){
+ var Q, Jscex, AsyncBuilder, __ref;
+ if (typeof module != 'undefined' && module !== null) {
+ module.exports = Q = require('q');
+ Jscex = require('jscex');
+ require('jscex-jit').init(Jscex);
+ require('jscex-async').init(Jscex);
+ } else {
+ Q == null && (Q = (__ref = this.Q) != null
+ ? __ref
+ : (function(){
+ throw new Error("Q not available -- Please include it");
+ }()));
+ Jscex == null && (Jscex = (__ref = this.Jscex) != null
+ ? __ref
+ : (function(){
+ throw new Error("Jscex not available -- Please include jscex.min.js");
+ }()));
+ }
+ /* Our own monad that runs on Q promises */
+ AsyncBuilder = (function(){
+ AsyncBuilder.displayName = 'AsyncBuilder';
+ var prototype = AsyncBuilder.prototype, constructor = AsyncBuilder;
+ prototype.Start = function(_this, step){
+ var __;
+ __ = Q.defer();
+ step.next(_this, function(type, value, target){
+ switch (type) {
+ case 'normal':
+ case 'return':
+ __.resolve(value);
+ break;
+ case 'throw':
+ __.reject(value);
+ break;
+ default:
+ throw new Error("Unsupported type: " + type);
+ }
+ });
+ return __.promise;
+ };
+ prototype.Bind = function(promise, generator){
+ return {
+ next: function(_this, cb){
+ return promise.then(function(result){
+ var step;
+ try {
+ step = generator.call(_this, result);
+ } catch (e) {
+ return cb('throw', e);
+ }
+ step.next(_this, cb);
+ }, function(error){
+ cb('throw', error);
+ });
+ }
+ };
+ };
+ function AsyncBuilder(){}
+ return AsyncBuilder;
+ }());
+ __importAll(AsyncBuilder.prototype, Jscex.BuilderBase.prototype);
+ Jscex.binders['async-q'] = '$await';
+ Jscex.builders['async-q'] = new AsyncBuilder;
+ Jscex.modules['async-q'] = true;
+ /* Compile a function containing the special $await keyword.
+
+ Once invoked, we implicitly start the task, and return a
+ deferred Promise object representing its result.
+ */
+ Q.async.$ = function(cb){
+ return Jscex.compile('async-q', cb).replace(/(Jscex.builders\["async-q"\])/, 'Q.async.$.$1');
+ };
+ /* Turn off Jscex logging by default */
+ Jscex.logger.level = 999;
+ Q.async.$.Jscex = Jscex;
+ function __importAll(obj, src){
+ for (var key in src) obj[key] = src[key];
+ return obj;
+ }
+}).call(this);
@@ -0,0 +1,15 @@
+Q = require './q-jscex'
+HTTP = require \q-http
+say = !-> console.log it; console.log ''
+
+fetch = eval Q.async.$ (url) ->
+ html = $await HTTP.read url
+ return html.toString(\utf-8, 555, 600)
+
+say '[Demo: Fetching invalid host, expecting ENOENT...]'
+
+<- fetch \http://blog.zhaojie.error .fail say .fin
+
+say '[Demo: Fetching valid host, expecting snippet...]'
+
+fetch \http://blog.zhaojie.me .then say
@@ -0,0 +1,48 @@
+if module?
+ module.exports = Q = require \q
+ Jscex = require \jscex
+ require \jscex-jit .init Jscex
+ require \jscex-async .init Jscex
+else
+ Q ?= @Q ? throw new Error "Q not available -- Please include it"
+ Jscex ?= @Jscex ? throw new Error "Jscex not available -- Please include jscex.min.js"
+
+/* Our own monad that runs on Q promises */
+class AsyncBuilder
+ Start: (_this, step) ->
+ __ = Q.defer!
+ step.next _this, !(type, value, target) ->
+ switch type
+ | \normal \return => __.resolve value
+ | \throw => __.reject value
+ | otherwise => throw new Error "Unsupported type: #type"
+ return __.promise
+ Bind: (promise, generator) ->
+ return next: (_this, cb) -> promise.then(
+ !(result) ->
+ try step = generator.call _this, result
+ catch return cb \throw, e
+ step.next _this, cb
+ !(error) -> cb \throw, error
+ )
+
+AsyncBuilder:: <<<< Jscex.BuilderBase::
+
+Jscex.binders.\async-q = \$await
+Jscex.builders.\async-q = new AsyncBuilder
+Jscex.modules.\async-q = true
+
+/* Compile a function containing the special $await keyword.
+
+ Once invoked, we implicitly start the task, and return a
+ deferred Promise object representing its result.
+*/
+Q.async.$ = (cb) -> Jscex.compile(\async-q, cb).replace(
+ /(Jscex.builders\["async-q"\])/
+ 'Q.async.$.$1'
+)
+
+/* Turn off Jscex logging by default */
+Jscex.logger.level = 999
+
+Q.async.$.Jscex = Jscex

0 comments on commit a12b950

Please sign in to comment.