From 132706fd75c5782fed13e66d9b7a12194fbbdc92 Mon Sep 17 00:00:00 2001 From: Boris Yankov Date: Sat, 25 May 2013 18:42:10 +0300 Subject: [PATCH] Improve slightly jsDeferred --- jsdeferred/jsdeferred-tests.ts | 1474 ++++++++++++++++---------------- jsdeferred/jsdeferred.d.ts | 115 +-- 2 files changed, 783 insertions(+), 806 deletions(-) diff --git a/jsdeferred/jsdeferred-tests.ts b/jsdeferred/jsdeferred-tests.ts index a42119bce2..673c294de3 100644 --- a/jsdeferred/jsdeferred-tests.ts +++ b/jsdeferred/jsdeferred-tests.ts @@ -1,858 +1,858 @@ /// /// -declare function alert(a:any):void; -declare function log(a:any):void; +declare function alert(a: any): void; +declare function log(a: any): void; interface DeferredizedJQueryStatic extends JQueryStatic { - get(url:string, data?:any, success?:any, dataType?:any): Deferred; + //get (url: string, data?: any, success?: any, dataType?: any): Deferred; } declare var $: DeferredizedJQueryStatic; declare interface http { - get(url:string):Deferred; + get (url: string): Deferred; } /***** jsDoc case *****/ - // constructor -(()=> { - var d = new Deferred(); - var d = Deferred(); +// constructor +(() => { + var d = new Deferred(); + var d = Deferred(); })(); // define -(()=> { - Deferred.define(); - $.get("/hoge").next(function (data) { - alert(data); - }). - parallel([$.get("foo.html"), $.get("bar.html")]).next(function (values) { - log($.map(values, function (v) { return v.length })); - if (values[1].match(/nextUrl:\s*(\S+)/)) { - return $.get(RegExp.$1).next(function (d) { - return d; - }); - } +(() => { + Deferred.define(); + $.get("/hoge").next(function (data) { + alert(data); }). - next(function (d) { - log(d.length); - }); + parallel([$.get("foo.html"), $.get("bar.html")]).next(function (values) { + log($.map(values, function (v) { return v.length })); + if (values[1].match(/nextUrl:\s*(\S+)/)) { + return $.get(RegExp.$1).next(function (d) { + return d; + }); + } + }). + next(function (d) { + log(d.length); + }); })(); // next -(()=> { - var d = new Deferred(); - d. - next(function () { - alert(1); - }). - next(function () { - alert(2); - }); - d.call(); +(() => { + var d = new Deferred(); + d. + next(function () { + alert(1); + }). + next(function () { + alert(2); + }); + d.call(); })(); // error -(()=> { - var d = new Deferred(); - d. - next(function () { - alert(1); - throw "foo"; - }). - next(function () { - alert('not shown'); - }). - error(function (e) { - alert(e); //=> "foo" - }); - d.call(); +(() => { + var d = new Deferred(); + d. + next(function () { + alert(1); + throw "foo"; + }). + next(function () { + alert('not shown'); + }). + error(function (e) { + alert(e); //=> "foo" + }); + d.call(); })(); // call -(()=> { - var d = new Deferred(); - setTimeout(function () { - d.call('value'); - }, 100); - return d; +(() => { + var d = new Deferred(); + setTimeout(function () { + d.call('value'); + }, 100); + return d; })(); // fail -(()=> { - var d = new Deferred(); - var x = new XMLHttpRequest(); - x.onreadystatechange = function () { - if (x.readyState == 4) { - if (x.status == 200) d.call(x); else d.fail(x); - } - }; - return d; +(() => { + var d = new Deferred(); + var x = new XMLHttpRequest(); + x.onreadystatechange = function () { + if (x.readyState == 4) { + if (x.status == 200) d.call(x); else d.fail(x); + } + }; + return d; })(); // chain -(()=> { - chain( - function () { - return wait(0.5); - }, - function (w) { - throw "foo"; - }, - function error(e) { - alert(e); - }, - [ +(() => { + chain( function () { - return wait(1); + return wait(0.5); }, - function () { - return wait(2); + function (w) { + throw "foo"; + }, + function error(e) { + alert(e); + }, + [ + function () { + return wait(1); + }, + function () { + return wait(2); + } + ], + function (result) { + alert([result[0], result[1]]); + }, + { + foo: wait(1), + bar: wait(1) + }, + function (result) { + alert([result.foo, result.bar]); + }, + function error(e) { + alert(e); } - ], - function (result) { - alert([ result[0], result[1] ]); - }, - { - foo: wait(1), - bar: wait(1) - }, - function (result) { - alert([ result.foo, result.bar ]); - }, - function error(e) { - alert(e); - } - ); + ); })(); // wait -(()=> { - wait(1).next(function (elapsed) { - log(elapsed); //=> may be 990-1100 - }); +(() => { + wait(1).next(function (elapsed) { + log(elapsed); //=> may be 990-1100 + }); })(); // call -(()=> { - next(function () { - function pow(x, n) { - function _pow(n, r) { - print([n, r]); - if (n == 0) return r; - return call(_pow, n - 1, x * r); - } +(() => { + next(function () { + function pow(x, n) { + function _pow(n, r) { + print([n, r]); + if (n == 0) return r; + return call(_pow, n - 1, x * r); + } - return call(_pow, n, 1); - } + return call(_pow, n, 1); + } - return call(pow, 2, 10); - }). - next(function (r) { - print([r, "end"]); - }); + return call(pow, 2, 10); + }). + next(function (r) { + print([r, "end"]); + }); })(); // parallel -(()=> { - parallel([ - $.get("foo.html"), - $.get("bar.html") - ]).next(function (values) { - values[0] //=> foo.html data - values[1] //=> bar.html data +(() => { + parallel([ + $.get("foo.html"), + $.get("bar.html") + ]).next(function (values) { + values[0] //=> foo.html data + values[1] //=> bar.html data }); - parallel({ - foo: $.get("foo.html"), - bar: $.get("bar.html") - }).next(function (values) { - values.foo //=> foo.html data - values.bar //=> bar.html data + parallel({ + foo: $.get("foo.html"), + bar: $.get("bar.html") + }).next(function (values) { + values.foo //=> foo.html data + values.bar //=> bar.html data }); })(); // loop -(()=> { - //=> loop 1 to 100 - loop({begin: 1, end: 100, step: 10}, function (n, o) { - for (var i = 0; i < o.step; i++) { - log(n + i); - } - }); +(() => { + //=> loop 1 to 100 + loop({ begin: 1, end: 100, step: 10 }, function (n, o) { + for (var i = 0; i < o.step; i++) { + log(n + i); + } + }); - //=> loop 10 times with sleeping 1 sec in each loop. - loop(10, function (n) { - log(n); - return wait(1); - }); + //=> loop 10 times with sleeping 1 sec in each loop. + loop(10, function (n) { + log(n); + return wait(1); + }); })(); // repeat -(()=> { - repeat(10, function (i) { - i //=> 0,1,2,3,4,5,6,7,8,9 - }); +(() => { + repeat(10, function (i) { + i //=> 0,1,2,3,4,5,6,7,8,9 + }); })(); // register -(()=> { - // Deferred.register("loop", loop); +(() => { + // Deferred.register("loop", loop); - // Global Deferred function - loop(10,function (n) { - print(n); - }). - // Registered Deferred.prototype.loop + // Global Deferred function loop(10, function (n) { - print(n); - }); + print(n); + }). + // Registered Deferred.prototype.loop + loop(10, function (n) { + print(n); + }); })(); // connect -(()=> { - var timeout = Deferred.connect(setTimeout, { target: window, ok: 0 }); - timeout(1).next(function () { - alert('after 1 sec'); - }); +(() => { + var timeout = Deferred.connect(setTimeout, { target: window, ok: 0 }); + timeout(1).next(function () { + alert('after 1 sec'); + }); - var timeout = Deferred.connect(window, "setTimeout"); - timeout(1).next(function () { - alert('after 1 sec'); - }); + var timeout = Deferred.connect(window, "setTimeout"); + timeout(1).next(function () { + alert('after 1 sec'); + }); })(); // retry -(()=> { - Deferred.retry(3,function () { - return http.get('foo.html'); - }). - next(function (res) { - res //=> response if succeeded +(() => { + Deferred.retry(3, function () { + return http.get('foo.html'); }). - error(function (e) { - e //=> error if all try failed - }); + next(function (res) { + res //=> response if succeeded + }). + error(function (e) { + e //=> error if all try failed + }); })(); /***** Tutorial case *****/ -(()=> { - Deferred.define(); +(() => { + Deferred.define(); - next(function () { - alert("Hello!"); - return wait(5); - }). next(function () { - alert("World!"); - }); - - Deferred.next(function () { - alert("Hello!"); - return Deferred.wait(5); - }). - next(function () { - alert("World!"); - }); - - // http.get is assumed to be a function that takes a URI as an argument and returns a Deferred instance - var results = []; - next(function () { - return http.get("/foo.json").next(function (data) { - results.push(data); - }); - }). - next(function () { - return http.get("/baz.json").next(function (data) { - results.push(data); - }); - }). - next(function () { - return http.get("/baz.json").next(function (data) { - results.push(data); - }); - }). - next(function () { - alert(results); - }); - - var wants = ["/foo.json", "/bar.json", "/baz.json"]; - var results = []; - loop(wants.length,function (i) { - return http.get(wants[i]).next(function (data) { - results.push(data); - }); - }). - next(function () { - alert(results); - }); - - parallel([ - http.get("/foo.json"), - http.get("/bar.json"), - http.get("/baz.json") - ]). - next(function (results) { - alert(results); - }); - - next(function () { - // something 1 - }). - next(function () { - // asynchronous process - throw "error!"; - }). - next(function () { - // something 2 (not executed as an error occurs in the previous process) - }); - - next(function () { - // something 1 - }). - next(function () { - // asynchronous process - throw "error!"; - }). - next(function () { - // something 2 (not executed as an error occurs in the previous process) - }). - error(function (e) { - alert(e); - }); - - next(function () { - // something 1 - }). - next(function () { - // asynchronous process - throw "error!"; - }). - error(function (e) { - alert(e); - }). - next(function () { - // something 2 (executed since the exception would already be handled) - }). - error(function (e) { - alert(e); - }); - - next(function () { - alert("Hello!"); - return wait(5); - }). - next(function () { - alert("World!"); - }); - - next(function () { - alert(1); - return next(function () { - alert(2); + alert("Hello!"); + return wait(5); }). next(function () { - alert(3); + alert("World!"); }); - }). + + Deferred.next(function () { + alert("Hello!"); + return Deferred.wait(5); + }). + next(function () { + alert("World!"); + }); + + // http.get is assumed to be a function that takes a URI as an argument and returns a Deferred instance + var results = []; next(function () { - alert(4); + return http.get("/foo.json").next(function (data) { + results.push(data); + }); + }). + next(function () { + return http.get("/baz.json").next(function (data) { + results.push(data); + }); + }). + next(function () { + return http.get("/baz.json").next(function (data) { + results.push(data); + }); + }). + next(function () { + alert(results); + }); + + var wants = ["/foo.json", "/bar.json", "/baz.json"]; + var results = []; + loop(wants.length, function (i) { + return http.get(wants[i]).next(function (data) { + results.push(data); + }); + }). + next(function () { + alert(results); + }); + + parallel([ + http.get("/foo.json"), + http.get("/bar.json"), + http.get("/baz.json") + ]). + next(function (results) { + alert(results); + }); + + next(function () { + // something 1 + }). + next(function () { + // asynchronous process + throw "error!"; + }). + next(function () { + // something 2 (not executed as an error occurs in the previous process) + }); + + next(function () { + // something 1 + }). + next(function () { + // asynchronous process + throw "error!"; + }). + next(function () { + // something 2 (not executed as an error occurs in the previous process) + }). + error(function (e) { + alert(e); + }); + + next(function () { + // something 1 + }). + next(function () { + // asynchronous process + throw "error!"; + }). + error(function (e) { + alert(e); + }). + next(function () { + // something 2 (executed since the exception would already be handled) + }). + error(function (e) { + alert(e); + }); + + next(function () { + alert("Hello!"); + return wait(5); + }). + next(function () { + alert("World!"); + }); + + next(function () { + alert(1); + return next(function () { + alert(2); + }). + next(function () { + alert(3); + }); + }). + next(function () { + alert(4); + }); + + var http = {} + http.get = function (uri) { + var deferred = new Deferred(); + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + deferred.call(xhr); + } else { + deferred.fail(xhr); + } + } + }; + deferred.canceller = function () { xhr.abort() }; + return deferred; + } + + loop(1000, function (n) { + // heavy process }); - var http = {} - http.get = function (uri) { - var deferred = new Deferred(); - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - deferred.call(xhr); - } else { - deferred.fail(xhr); - } - } + function repeat(n, f) { + var i = 0, end = {}, ret = null; + return Deferred.next(function () { + var t = (new Date()).getTime(); + divide: { + do { + if (i >= n) break divide; + ret = f(i++); + } while ((new Date()).getTime() - t < 20); + return Deferred.call(arguments.callee); + } + }); + } + + next(function () { + console.log("start"); + }). + next(function () { + function pow(x, n) { + function _pow(n, r) { + console.log([n, r]); + if (n == 0) return r; + return call(_pow, n - 1, x * r); + } + + return call(_pow, n, 1); + } + + return call(pow, 2, 10); + }). + next(function (r) { + console.log([r, "end"]); + }). + error(function (e) { + alert(e); + }) + + loop(10, function (i) { + console.log(i) + }); + + $.get("README.markdown").next(function (data) { + console.log(data); + }); + +})(); + +(() => { + console.log("start. gathering data."); + + parallel([$.get("README.markdown"), $.get("ChangeLog")]). + next(function (values) { + var lengths = $.map(values, function (i) { return i.length }); + console.log(lengths.join(", ")); + }); +})(); + +(() => { + console.log("start. gathering data."); + + parallel({ html: $.get("README.markdown"), js: $.get("ChangeLog") }). + next(function (values) { + console.log(["html=", values.html.length, " js=", values.js.length].join("")); + }); +})(); + +(() => { + console.log("start. wait 3 sec."); + + var list = []; + var printAndReturn = function (i) { + console.log(i + "msec elapsed"); + return i; }; - deferred.canceller = function () { xhr.abort() }; - return deferred; - } + list.push(wait(0).next(printAndReturn)); + list.push(wait(1).next(printAndReturn)); + list.push(wait(2).next(printAndReturn)); + list.push(wait(3).next(printAndReturn)); - loop(1000, function (n) { - // heavy process - }); - - function repeat(n, f) { - var i = 0, end = {}, ret = null; - return Deferred.next(function () { - var t = (new Date()).getTime(); - divide: { - do { - if (i >= n) break divide; - ret = f(i++); - } while ((new Date()).getTime() - t < 20); - return Deferred.call(arguments.callee); - } + parallel(list).next(function (values) { + console.log("Completed. values: " + values.join(", ")); }); - } +})(); - next(function () { - console.log("start"); - }). +(() => { + var queue = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + var workers = new Array(2); + var work = function (job) { + console.log('working... ' + job); + return wait(Math.random() * 4); + }; + + for (var i = 0, len = workers.length; i < len; i++) { + workers[i] = next(function me() { + var job = queue.shift(); + if (!job) return; + + console.log("start worker: " + job); + return next(function () { return job }). + next(work). + next(me); + }). + error(function (e) { + alert(e); + }); + } + + parallel(workers).next(function () { + console.log('all done!'); + }); +})(); + +(() => { next(function () { - function pow(x, n) { - function _pow(n, r) { - console.log([n, r]); - if (n == 0) return r; - return call(_pow, n - 1, x * r); - } - - return call(_pow, n, 1); - } - - return call(pow, 2, 10); - }). - next(function (r) { - console.log([r, "end"]); - }). - error(function (e) { - alert(e); - }) - - loop(10, function (i) { - console.log(i) - }); - - $.get("README.markdown").next(function (data) { - console.log(data); - }); - -})(); - -(()=> { - console.log("start. gathering data."); - - parallel([$.get("README.markdown"), $.get("ChangeLog")]). - next(function (values) { - var lengths = $.map(values, function (i) { return i.length }); - console.log(lengths.join(", ")); - }); -})(); - -(()=> { - console.log("start. gathering data."); - - parallel({html: $.get("README.markdown"), js: $.get("ChangeLog")}). - next(function (values) { - console.log(["html=", values.html.length, " js=", values.js.length].join("")); - }); -})(); - -(()=> { - console.log("start. wait 3 sec."); - - var list = []; - var printAndReturn = function (i) { - console.log(i + "msec elapsed"); - return i; - }; - list.push(wait(0).next(printAndReturn)); - list.push(wait(1).next(printAndReturn)); - list.push(wait(2).next(printAndReturn)); - list.push(wait(3).next(printAndReturn)); - - parallel(list).next(function (values) { - console.log("Completed. values: " + values.join(", ")); - }); -})(); - -(()=> { - var queue = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - var workers = new Array(2); - var work = function (job) { - console.log('working... ' + job); - return wait(Math.random() * 4); - }; - - for (var i = 0, len = workers.length; i < len; i++) { - workers[i] = next(function me() { - var job = queue.shift(); - if (!job) return; - - console.log("start worker: " + job); - return next(function () { return job }). - next(work). - next(me); + var sum = 0; + return loop({ end: 100000, step: 1000 }, function (n, o) { + console.log(["Processing divided loop:n=", n, ", sum=", sum, " last?=", o.last].join("")); + for (var i = 0; i < o.step; i++) { + // console.log(i + n); + sum += i + n; + } + console.log(["sum=", sum].join("")); + return sum; + }); }). + next(function (e) { + console.log("Result:" + e); + console.log("end"); + }). error(function (e) { - alert(e); + console.log(e); }); - } - - parallel(workers).next(function () { - console.log('all done!'); - }); })(); -(()=> { - next(function () { - var sum = 0; - return loop({end: 100000, step: 1000}, function (n, o) { - console.log(["Processing divided loop:n=", n, ", sum=", sum, " last?=", o.last].join("")); - for (var i = 0; i < o.step; i++) { - // console.log(i + n); - sum += i + n; - } - console.log(["sum=", sum].join("")); - return sum; - }); - }). - next(function (e) { - console.log("Result:" + e); - console.log("end"); - }). - error(function (e) { - console.log(e); +(() => { + loop({ begin: 1, end: 100, step: 10 }, function (n, o) { + console.log(["Processing divided loop:n=", n, " last?=", o.last].join("")); + for (var i = 0; i < o.step; i++) { + var j = n + i; + console.log(j); + } }); })(); -(()=> { - loop({begin: 1, end: 100, step: 10}, function (n, o) { - console.log(["Processing divided loop:n=", n, " last?=", o.last].join("")); - for (var i = 0; i < o.step; i++) { - var j = n + i; - console.log(j); - } - }); +(() => { + Deferred.repeat(100, function (n, o) { + console.log(n); + for (var i = 0; i < Math.pow(n, 2); i++) { + for (var j = n; j; j--); + } + }); })(); -(()=> { - Deferred.repeat(100, function (n, o) { - console.log(n); - for (var i = 0; i < Math.pow(n, 2); i++) { - for (var j = n; j; j--); - } - }); +(() => { + loop(10, function (n) { + console.log(n); + return wait(0.1); + }); + + loop(10, function (n) { + console.log(String.fromCharCode(97 + n)); + return wait(0.2); + }); })(); -(()=> { - loop(10, function (n) { - console.log(n); - return wait(0.1); - }); - - loop(10, function (n) { - console.log(String.fromCharCode(97 + n)); - return wait(0.2); - }); -})(); - -(()=> { - console.log(0); - loop(10,function (n) { - console.log(n); - return n; - }). - wait(1). - loop(10,function (n) { - var c = String.fromCharCode(97 + n); - console.log(c); - return c; +(() => { + console.log(0); + loop(10, function (n) { + console.log(n); + return n; }). + wait(1). + loop(10, function (n) { + var c = String.fromCharCode(97 + n); + console.log(c); + return c; + }). + next(function (i) { + console.log("end"); + }). + error(function (e) { + alert(e); + }); +})(); + +(() => { + loop(5, function (i, o) { + console.log(i); + return o.last ? i : wait(1); + }). + next(function (e) { + console.log("end [" + e + "]"); + }). + error(function (e) { + console.log(e); + }); +})(); + +(() => { next(function (i) { - console.log("end"); - }). - error(function (e) { - alert(e); - }); -})(); - -(()=> { - loop(5,function (i, o) { - console.log(i); - return o.last ? i : wait(1); - }). - next(function (e) { - console.log("end [" + e + "]"); - }). - error(function (e) { - console.log(e); - }); -})(); - -(()=> { - next(function (i) { - function delayloop(i) { - console.log(i++); - if (i < 5) { - return wait(1).next(function () { - return call(delayloop, i); - }); - } - } - - return call(delayloop, 0); - }). - next(function (e) { - console.log("end"); - }). - error(function (e) { - console.log(e); - }); -})(); - -(()=> { - function callcc(fun) { - var error = new Deferred(); - return call(function () { - // JSDeferred passes current Deferred Object to this. - var ccdeferred = this; - // Call with current continuation (calling Deferred.next) - return fun(function (a) { - ccdeferred._next.call(a); - throw error - }); - }). - error(function (e) { - // Current Deferred chain must be stopped - if (e === error) { - return e; - } else { - throw e; + function delayloop(i) { + console.log(i++); + if (i < 5) { + return wait(1).next(function () { + return call(delayloop, i); + }); + } } - }); - } - callcc(function (cont) { - return 10 * 10 * cont(20); - }). - next(function (val) { - console.log("callcc1 returns:" + val); - }); - // should show "callcc1 returns:20" - - var cont; - var i = 0; - callcc(function (c) { - cont = c; - return 10; - }). - next(function (val) { - console.log("callcc2 returns:" + val); - if (!i++) cont(20); - }); - // should show "callcc2 returns:10", "callcc returns:20" -})(); - -(()=> { - function callcc(fun) { - var error = new Deferred(); - return call(function () { - // JSDeferred passes current Deferred Object to this. - var ccdeferred = this; - // Call with current continuation (calling Deferred.next) - return fun(function (a) { - ccdeferred._next.call(a); - throw error - }); + return call(delayloop, 0); }). - error(function (e) { - // Current Deferred chain must be stopped - if (e === error) { - return e; - } else { - throw e; - } - }); - } - - // http://www.sampou.org/scheme/t-y-scheme/t-y-scheme-Z-H-16.html#node_chap_14 - // Just port above. - function amb() { - var alts = arguments; - var prevAmbFail = amb.ambFail; - - return callcc(function (sk) { - return loop(alts.length,function (i) { - var alt = alts[i]; - return callcc(function (fk) { - amb.ambFail = function () { - amb.ambFail = prevAmbFail; - return fk("fail"); - }; - return sk(alt); - }); + next(function (e) { + console.log("end"); }). - next(prevAmbFail); - }); - } - - amb.ambFail = function () { throw "amb tree exhausted" }; - - // Utility function - function amb1(ambvars) { - var f = wait(0); - var vars = {}; - for (var k in ambvars) if (ambvars.hasOwnProperty(k)) (function (name, val) { - console.log(name); - f = f.next(function () { - return amb.apply(this, val).next(function (i) { - vars[name] = i; - return vars; - }); + error(function (e) { + console.log(e); }); - })(k, ambvars[k]); +})(); - return f; - } - - function assert(cond) { - if (!cond) throw amb(); - } - - // http://mayokara.info/note/view/251 - Array.prototype.uniq = function () { - for (var i = 0, l = this.length; i < l; i++) { - if (this.indexOf(this[i]) < i) { - this.splice(i--, l-- && 1); - } +(() => { + function callcc(fun) { + var error = new Deferred(); + return call(function () { + // JSDeferred passes current Deferred Object to this. + var ccdeferred = this; + // Call with current continuation (calling Deferred.next) + return fun(function (a) { + ccdeferred._next.call(a); + throw error + }); + }). + error(function (e) { + // Current Deferred chain must be stopped + if (e === error) { + return e; + } else { + throw e; + } + }); } - return this; - }; - amb1({ - baker : [1, 2, 3, 4, 5], - cooper : [1, 2, 3, 4, 5], - fletcher: [1, 2, 3, 4, 5], - miller : [1, 2, 3, 4, 5], - smith : [1, 2, 3, 4, 5] - }). - next(function (vars) { - with (vars) { - console.log(vars); - // 簡易 distinct - assert([baker, cooper, fletcher, miller, smith].uniq().length == 5); - console.log("distinct passed"); - assert(baker != 5); - assert(cooper != 1); - assert(fletcher != 1 && fletcher != 5); - assert(miller > cooper); - assert(Math.abs(smith - fletcher) != 1); - assert(Math.abs(fletcher - cooper) != 1); - - return vars; - } + callcc(function (cont) { + return 10 * 10 * cont(20); }). - next(function (vars) { - with (vars) { - console.log("solved"); - console.log(vars); - alert(uneval(vars)); - } - }). - error(function (e) { - alert(e) - }); -})(); - -(()=> { - var d1 = new Deferred(); - d1.callback.ok = function () { - alert("1"); - }; - - var d2 = new Deferred(); - d2.callback.ok = function () { - alert("2"); - }; - - // Set d2 as continuation of d1. - d1._next = d2; - - // Invoke the chain. - d1.call(); -})(); - -(()=> { - next(function () { // this `next` is global function - alert("1"); - }). - next(function () { // this `next` is Deferred#next - alert("2"); - }). - next(function () { - alert("3"); - }); -})(); - -(()=> { - next(function () { - alert("1"); - }). - next(function () { - alert("2"); - // child Deferred - return next(function () { - alert("3"); + next(function (val) { + console.log("callcc1 returns:" + val); }); - }). - next(function () { - alert("4"); - }); -})(); + // should show "callcc1 returns:20" -(()=> { - next(function () { - alert("1"); - }). - next(function () { - alert("2"); - var d = next(function () { - alert("3"); + var cont; + var i = 0; + callcc(function (c) { + cont = c; + return 10; + }). + next(function (val) { + console.log("callcc2 returns:" + val); + if (!i++) cont(20); }); - d._next = this._next; - this.cancel(); - }). - next(function () { - alert("4"); - }); + // should show "callcc2 returns:10", "callcc returns:20" })(); -(()=> { - next(function () { - alert("1"); - }). - next(function () { - alert("2"); +(() => { + function callcc(fun) { + var error = new Deferred(); + return call(function () { + // JSDeferred passes current Deferred Object to this. + var ccdeferred = this; + // Call with current continuation (calling Deferred.next) + return fun(function (a) { + ccdeferred._next.call(a); + throw error + }); + }). + error(function (e) { + // Current Deferred chain must be stopped + if (e === error) { + return e; + } else { + throw e; + } + }); + } + + // http://www.sampou.org/scheme/t-y-scheme/t-y-scheme-Z-H-16.html#node_chap_14 + // Just port above. + function amb() { + var alts = arguments; + var prevAmbFail = amb.ambFail; + + return callcc(function (sk) { + return loop(alts.length, function (i) { + var alt = alts[i]; + return callcc(function (fk) { + amb.ambFail = function () { + amb.ambFail = prevAmbFail; + return fk("fail"); + }; + return sk(alt); + }); + }). + next(prevAmbFail); + }); + } + + amb.ambFail = function () { throw "amb tree exhausted" }; + + // Utility function + function amb1(ambvars) { + var f = wait(0); + var vars = {}; + for (var k in ambvars) if (ambvars.hasOwnProperty(k)) (function (name, val) { + console.log(name); + f = f.next(function () { + return amb.apply(this, val).next(function (i) { + vars[name] = i; + return vars; + }); + }); + })(k, ambvars[k]); + + return f; + } + + function assert(cond) { + if (!cond) throw amb(); + } + + // http://mayokara.info/note/view/251 + Array.prototype.uniq = function () { + for (var i = 0, l = this.length; i < l; i++) { + if (this.indexOf(this[i]) < i) { + this.splice(i--, l-- && 1); + } + } + return this; + }; + + amb1({ + baker: [1, 2, 3, 4, 5], + cooper: [1, 2, 3, 4, 5], + fletcher: [1, 2, 3, 4, 5], + miller: [1, 2, 3, 4, 5], + smith: [1, 2, 3, 4, 5] + }). + next(function (vars) { + with (vars) { + console.log(vars); + // 簡易 distinct + assert([baker, cooper, fletcher, miller, smith].uniq().length == 5); + console.log("distinct passed"); + assert(baker != 5); + assert(cooper != 1); + assert(fletcher != 1 && fletcher != 5); + assert(miller > cooper); + assert(Math.abs(smith - fletcher) != 1); + assert(Math.abs(fletcher - cooper) != 1); + + return vars; + } + }). + next(function (vars) { + with (vars) { + console.log("solved"); + console.log(vars); + alert(uneval(vars)); + } + }). + error(function (e) { + alert(e) + }); +})(); + +(() => { + var d1 = new Deferred(); + d1.callback.ok = function () { + alert("1"); + }; + + var d2 = new Deferred(); + d2.callback.ok = function () { + alert("2"); + }; + + // Set d2 as continuation of d1. + d1._next = d2; + + // Invoke the chain. + d1.call(); +})(); + +(() => { + next(function () { // this `next` is global function + alert("1"); + }). + next(function () { // this `next` is Deferred#next + alert("2"); + }). next(function () { - alert("3"); - }). - next(function () { - alert("4"); - }); - }); + alert("3"); + }); })(); -(()=> { - next(function () { - throw "Error"; - }). - error(function (e) { - expect("Errorback called", "Error", e); - return e; // recovering error +(() => { + next(function () { + alert("1"); }). - next(function (e) { - expect("Callback called", "Error", e); - throw "Error2"; - }). - next(function (e) { - // This process is not called because - // the error is not recovered. - ng("Must not be called!!"); - }). - error(function (e) { - expect("Errorback called", "Error2", e); - }); + next(function () { + alert("2"); + // child Deferred + return next(function () { + alert("3"); + }); + }). + next(function () { + alert("4"); + }); +})(); + +(() => { + next(function () { + alert("1"); + }). + next(function () { + alert("2"); + var d = next(function () { + alert("3"); + }); + d._next = this._next; + this.cancel(); + }). + next(function () { + alert("4"); + }); +})(); + +(() => { + next(function () { + alert("1"); + }). + next(function () { + alert("2"); + next(function () { + alert("3"); + }). + next(function () { + alert("4"); + }); + }); +})(); + +(() => { + next(function () { + throw "Error"; + }). + error(function (e) { + expect("Errorback called", "Error", e); + return e; // recovering error + }). + next(function (e) { + expect("Callback called", "Error", e); + throw "Error2"; + }). + next(function (e) { + // This process is not called because + // the error is not recovered. + ng("Must not be called!!"); + }). + error(function (e) { + expect("Errorback called", "Error2", e); + }); })(); diff --git a/jsdeferred/jsdeferred.d.ts b/jsdeferred/jsdeferred.d.ts index 1e354e7ee5..e8bb46e77f 100644 --- a/jsdeferred/jsdeferred.d.ts +++ b/jsdeferred/jsdeferred.d.ts @@ -4,95 +4,72 @@ // Definitions: https://github.com/borisyankov/DefinitelyTyped interface Loop { - begin:number; - end:number; - step:number; + begin: number; + end: number; + step: number; } interface ConnectOption { - target:any; - args?:any[]; - ok?:number; - ng?:number; + target: any; + args?: any[]; + ok?: number; + ng?: number; } interface RetryOption { - wait:number; + wait: number; } -interface DeferredizedFunction { (...arg:any[]):Deferred; } -interface DeferredizedFunctionWithNumber { (n:number):Deferred; } -interface FunctionWithNumber { (i:number); } -interface ErrorCallback { (d:Deferred, ...args:any[]); } +interface DeferredizedFunction { (...arg: any[]): Deferred; } +interface DeferredizedFunctionWithNumber { (n: number): Deferred; } +interface FunctionWithNumber { (i: number); } +interface ErrorCallback { (d: Deferred, ...args: any[]); } declare class Deferred { - static methods:string[]; + static methods: string[]; + static isDeferred(obj: any): bool; + static next(fun: Function): Deferred; + static chain(...args: any[]): Deferred; + static wait(n: number): Deferred; + static call(fun?: Function, ...args: any[]): Deferred; + static parallel(dl: any): Deferred; + static earlier(dl: any): Deferred; - static isDeferred(obj:any):bool; + static loop(n: number, fun: FunctionWithNumber): Deferred; + static loop(n: Loop, fun: FunctionWithNumber): Deferred; - static next(fun:Function):Deferred; + static repeat(n: number, fun: FunctionWithNumber): Deferred; + static register(name: string, fun: DeferredizedFunction): void; - static chain(...args:any[]):Deferred; + static connect(funo: any, options: string): DeferredizedFunction; + static connect(funo: Function, options?: ConnectOption): DeferredizedFunction; - static wait(n:number):Deferred; + static retry(retryCount: number, funcDeferred: DeferredizedFunctionWithNumber, options?: RetryOption): Deferred; + static define(obj?: any, list?: string[]): any; - static call(fun?:Function, ...args:any[]):Deferred; + constructor(); - static parallel(dl:any):Deferred; - - static earlier(dl:any):Deferred; - - static loop(n:number, fun:FunctionWithNumber):Deferred; - - static loop(n:Loop, fun:FunctionWithNumber):Deferred; - - static repeat(n:number, fun:FunctionWithNumber):Deferred; - - static register(name:string, fun:DeferredizedFunction):void; - - static connect(funo:any, options:string):DeferredizedFunction; - - static connect(funo:Function, options?:ConnectOption):DeferredizedFunction; - - static retry(retryCount:number, funcDeferred:DeferredizedFunctionWithNumber, options?:RetryOption):Deferred; - - static define(obj?:any, list?:string[]):any; - - constructor(); - - next(fun:Function):Deferred; - - wait(n:number):Deferred; - - error(fun:ErrorCallback):Deferred; - - call(val?:any):Deferred; - - fail(err:any):Deferred; - - cancel():Deferred; - - parallel(dl:any):Deferred; - - loop(n:number, fun:FunctionWithNumber):Deferred; - - loop(n:Loop, fun:FunctionWithNumber):Deferred; + next(fun: Function): Deferred; + wait(n: number): Deferred; + error(fun: ErrorCallback): Deferred; + call(val?: any): Deferred; + fail(err: any): Deferred; + cancel(): Deferred; + parallel(dl: any): Deferred; + loop(n: number, fun: FunctionWithNumber): Deferred; + loop(n: Loop, fun: FunctionWithNumber): Deferred; } -declare function chain(...args:any[]):Deferred; +declare function chain(...args: any[]): Deferred; +declare function wait(n: number): Deferred; +declare function call(fun?: Function, ...args: any[]): Deferred; +declare function parallel(dl: any): Deferred; +declare function earlier(dl: any): Deferred; -declare function wait(n:number):Deferred; +declare function loop(n: number, fun: FunctionWithNumber): Deferred; +declare function loop(n: Loop, fun: FunctionWithNumber): Deferred; -declare function call(fun?:Function, ...args:any[]):Deferred; - -declare function parallel(dl:any):Deferred; - -declare function earlier(dl:any):Deferred; - -declare function loop(n:number, fun:FunctionWithNumber):Deferred; -declare function loop(n:Loop, fun:FunctionWithNumber):Deferred; - -declare function repeat(n:number, fun:FunctionWithNumber):Deferred; \ No newline at end of file +declare function repeat(n: number, fun: FunctionWithNumber): Deferred; \ No newline at end of file