深入浅出Jscex
- 2. • / / Jeffrey Zhao /
•
• http://blog.zhaojie.me/
• @
• F#, JavaScript, Scala, C#, Python, .NET, Mono...
• Java
- 4. Jscex
•
• Jscex JavaScript
•
• Jscex /
• JavaScript /
• ECMAScript 3
- 6. var compare = function (x, y) {
return x - y;
}
var swap = function (a, i, j) {
var t = a[i]; a[i] = a[j]; a[j] = t;
}
var bubbleSort = function (array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
if (compare(array[y], array[y + 1]) > 0) {
swap(array, y, y + 1);
}
}
}
}
- 7. var compare = function (x, y, callback) { var innerLoop = function (array, x, y, callback) {
setTimeout(10, function () { if (y < array.length - x) {
callback(x - y); compare(array[y], array[y + 1], function (r) {
}); if (r > 0) {
} swap(array, y, y + 1, function () {
innerLoop(array, x, y + 1, callback);
var swap = function (a, i, j, callback) { });
var t = a[i]; a[i] = a[j]; a[j] = t; } else {
repaint(a); innerLoop(array, x, y + 1, callback);
}
setTimeout(20, callback); });
} } else {
callback();
var outerLoop = function (array, x, callback) { }
if (x < array) { }
innerLoop(array, x, 0, function () {
outerLoop(array, x + 1, callback); outerLoop(array, 0, function () {
}); console.log("done!");
} else { });
callback();
}
}
- 8. var compare = function (x, y, callback) { var innerLoop = function (array, x, y, callback) {
setTimeout(10, function () { if (y < array.length - x) {
callback(x - y); compare(array[y], array[y + 1], function (r) {
}); if (r > 0) {
} swap(array, y, y + 1, function () {
innerLoop(array, x, y + 1, callback);
var swap = function (a, i, j, callback) { });
var t = a[i]; a[i] = a[j]; a[j] = t; } else {
D
repaint(a); innerLoop(array, x, y + 1, callback);
}
M
setTimeout(20, callback); });
} } else {
T
callback();
var outerLoop = function (array, x, callback) { }
if (x < array) { }
innerLoop(array, x, 0, function () {
outerLoop(array, x + 1, callback); outerLoop(array, 0, function () {
}); console.log("done!");
} else { });
callback();
}
}
- 9. var compareAsync = eval(Jscex.compile("async", function (x, y) {
$await(Jscex.Async.sleep(10)); // each "compare" takes 10 ms.
return x - y;
}));
var swapAsync = eval(Jscex.compile("async", function (a, i, j) {
var t = a[i]; a[i] = a[j]; a[j] = t; // swap
repaint(a); // repaint after each swap
$await(Jscex.Async.sleep(20)); // each "swap" takes 20 ms.
}));
var bubbleSortAsync = eval(Jscex.compile("async", function (array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
var r = $await(compareAsync(array[y], array[y + 1]));
if (r > 0) $await(swapAsync(array, y, y + 1));
}
}
}));
http://files.zhaojie.me/jscex/samples/async/sorting-animations.html?bubble
- 10. var compareAsync = eval(Jscex.compile("async", function (x, y) {
$await(Jscex.Async.sleep(10)); // each "compare" takes 10 ms.
return x - y;
}));
var swapAsync = eval(Jscex.compile("async", function (a, i, j) {
var t = a[i]; a[i] = a[j]; a[j] = t; // swap
repaint(a); // repaint after each swap
$await(Jscex.Async.sleep(20)); // each "swap" takes 20 ms.
}));
var bubbleSortAsync = eval(Jscex.compile("async", function (array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
var r = $await(compareAsync(array[y], array[y + 1]));
if (r > 0) $await(swapAsync(array, y, y + 1));
}
}
}));
- 14. function () {
var res = $await(<async work>);
}
HTTP
UI
Web Service
- 15. var f = eval(Jscex.compile("async", function () {
var img = $await(readAsync("http://..."));
console.log("loaded!");
$await(writeAsync("./files/..."));
console.log("saved!");
}));
- 16. …
var f = eval('(function () {
var _b_ = Jscex.builders["async"];
return _b_.Start(this,
_b_.Delay(function () {
_b_.Bind(readAsync(...), function (img) {
console.log("loaded!");
return _b_.Bind(writeAsync(...), function () {
console.log("saved!");
return _b_.Normal();
});
});
})
);
})');
- 17. …
var f = (function () {
var _b_ = Jscex.builders["async"];
return _b_.Start(this,
_b_.Delay(function () {
_b_.Bind(readAsync(...), function (img) {
console.log("loaded!");
return _b_.Bind(writeAsync(...), function () {
console.log("saved!");
return _b_.Normal();
});
});
})
);
});
- 18. Express
var app = express.createServer();
app.get('/', function (req, res) {
/**
*
*
* 1.
* 2.
*
* 3. res
*
* “ ”
**/
});
app.listen(3000);
- 19. Jscex
app.getAsync('/', eval(Jscex.compile("async", function (req, res) {
var keys = $await(db.getKeysAsync(...));
var results = [];
for (var i = 0; i < keys.length; i++) {
var r = $await(cache.getAsync(keys[i]));
if (!r) {
r = $await(db.getItemAsync(keys[i]));
}
results.push(r);
}
res.send(generateList(results));
})));
- 20. I/O
• I/O
• Web
•
•
• I/O
•
- 21. var getItemAsync = eval(Jscex.compile("async", function (key) {
var res = $await(cache.getAsync(key));
if (res) return res;
return $await(db.getItemAsync(key));
}));
app.getAsync('/', eval(Jscex.compile("async", function (req, res) {
var keys = $await(db.getKeysAsync(...));
// “ ”
var tasks = keys.map(function (key) {
return getItemAsync(key);
});
//
var results = $await(Jscex.Async.parallel(tasks));
res.send(generateList(results));
})));
- 22. •
•
• $await(Jscex.Async.parallel(taskA, taskB))
• $await(taskA.continueWith(taskB))
• $await
•
•
•
• taskA.start(); $await(taskB); $await(taskA);
- 23. //
var i = 1;
conn.onAsync("data", eval(Jscex.compile("async", function () {
var id = i++;
$await(step1); console.log("step 1 - request " + id);
$await(step2); console.log("step 2 - request " + id);
/**
*
* step 1 - request 1
* step 1 - request 2
* step 2 - request 2
* step 2 - request 1
**/
})));
- 24. ... the principle we go by is, don't expect to see
a particular concurrency model put into C#
because there're many different concurrency
model ... it's more about finding things are
common to all kinds of concurrency ...
- Anders Hejlsberg
- 25. Erlang
var i = 0;
var agent = Agent.start(eval(Jscex.compile("async", function (mailbox) {
while (true) {
var id = i++;
var msg = $await(mailbox.receive());
$await(step1); console.log("step 1 - request " + id);
$await(step2); console.log("step 2 - request " + id);
}
})));
conn.on("data", function (data) {
// mailbox
agent.send(data);
});
- 27. • JavaScript
• while / for / for...in / do
• if / switch
• try...catch...finally
• return / break / continue / throw
•
• with
• break continue
• switch break
•
- 29. eval
Sample = {
//
compile: function (func) {
return "(" + func.toString() + ")";
},
// eval
compileEx: function (func) {
return eval("(" + func.toString() + ")");
}
}
- 30. eval
(function () {
var a = 1;
// f1
var f1 = eval(Sample.compile(function () {
alert(a);
}));
f1(); // “1”
// f2 Sample.compileEx
var f2 = Sample.compileEx(function () {
alert(a);
});
f2(); // “a ”
})();
- 31. • JavaScript
• “bind” $await
•
• “ ”
• “ ”
- 32. • JavaScript
•
•
• JIT
• JavaScript
- 33. “ ”
MyClass.prototype = {
get: function (n) {
...
},
calculateAsync: eval(Jscex.compile("async", function (n) {
var numbers = [];
for (var i = 0; i < n; i++)
numbers.push(i);
this.result = $await(make(numbers));
}))
}
- 34. “ ”
MyClass.prototype = {
get: function (n) {
...
}, Jscex
calculateAsync: eval(Jscex.compile("async", function (n) {
var numbers = [];
for (var i = 0; i < n; i++)
numbers.push(i);
this.result = $await(make(numbers));
}))
} Jscex
- 35. Jscex vs.
•
•
• Virtual Panel: How to Survive Asynchronous
Programming in JavaScript
•
• StratifiedJS
• Narrative JavaScript
• Streamline Jscex
- 37. Jscex vs.
•
•
•
•
• Jscex
• JavaScript
• JavaScript
• JavaScript
- 38. Streamline
• Jscex
• JavaScript
• JIT
•
• Jscex
•
• Yield – Resume vs. Asynchronous Callbacks – An
Equivalence
- 39. Streamline (input)
var bubbleSortAsync = function (array, _) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
if (compareAsync(array[y], array[y + 1], _) > 0)
swapAsync(array, y, y + 1, _);
}
}
}
- 40. Streamline (compiled)
var bubbleSortAsync = function __1(array, _) {
if (!_) {
return __future(__1, arguments, 1);
} if ((y < (array.length - x))) {
; return compareAsync(array[y], array[(y + 1)], __cb(_, function(__0, r) {
var __then = _; if ((r > 0)) {
var x = 0; return swapAsync(array, y, (y + 1), __cb(_, __then));
var __4 = false; }
return function(__break) { ;
var __loop = __nt(_, function() { return __then();
var __then = __loop; }));
if (__4) { }
x++; else {
} return __break();
else { }
__4 = true; ;
} });
; return __loop();
if ((x < array.length)) { }(__then);
var y = 0; }
var __3 = false; else {
return function(__break) { return __break();
var __loop = __nt(_, function() { }
var __then = __loop; ;
if (__3) { });
y++; return __loop();
} }(__then);
else { };
__3 = true;
}
;
http://sage.github.com/streamlinejs/examples/streamlineMe.html
- 41. Jecex (input)
var bubbleSortAsync = eval(Jscex.compile("async", function (array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
var r = $await(compareAsync(array[y], array[y + 1]));
if (r > 0)
$await(swapAsync(array, y, y + 1));
}
}
}));
- 42. Jecex (compiled)
var bubbleSortAsync = (function (array) {
var _b_ = Jscex.builders["async"];
return _b_.Start(this,
_b_.Delay(function () {
var x = 0;
return _b_.Loop(
function () { return x < array.length; },
function () { x++; },
_b_.Delay(function () {
var y = 0;
return _b_.Loop(
function () { return y < (array.length - x); },
function () { y++; }
_b_.Delay(function () {
return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) {
if (r > 0) {
return _b_.Bind(swapAsync(array, y, y + 1), function () {
return _b_.Normal();
});
} else {
return _b_.Normal();
}
});
}),
false
);
}),
false
);
})
);
})
- 43. Jecex (compiled)
var bubbleSortAsync = (function (array) {
var _b_ = Jscex.builders["async"];
return _b_.Start(this,
_b_.Delay(function () {
outer loop
var x = 0;
return _b_.Loop(
function () { return x < array.length; },
function () { x++; },
_b_.Delay(function () {
var y = 0;
return _b_.Loop(
inner loop function () { return y < (array.length - x); },
function () { y++; }
_b_.Delay(function () {
return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) {
if (r > 0) {
return _b_.Bind(swapAsync(array, y, y + 1), function () {
$await(compareAsync(...)) return _b_.Normal();
});
} else { $await(swapAsync(...))
return _b_.Normal();
}
});
}),
false
);
}),
false
);
})
);
})
- 44. Jscex
•
•
• “debugger”
• JavaScript
• Start, Delay, Combine
• Loop, Try
• Normal, Return, Break, Continue, Throw
• Bind
- 47. •
• JIT
• AOT
•
•
• Python C#
JavaScript 1.7
• …
- 50. //
var fib = eval(Jscex.compile("seq", function () {
var i = 0, j = 1;
while (true) {
$yield(i); // the bind operation
var t = i;
i = j;
j += t;
}
}));
var iter = fib().skip(10).take(10);
while (iter.moveNext()) {
console.log(iter.current);
}
- 51. … Maybe Monad
var maybeFunc = function () {
var maybeA = getA();
if (maybeA == Maybe.None) return Maybe.None;
var maybeB = getB();
if (maybeB == Maybe.None) return Maybe.None;
return maybeA.value + maybeB.value;
}
//
var maybeFunc = eval(Jscex.compile("maybe", function () {
var a = $try(getA());
var b = $try(getB());
return a + b;
}));
- 52. • “ ” “ ”
•
•
•
• Jscex /
- 53. for Loop
function (urls) {
for (var i = 0; i < urls.length; i++) {
$await(requestAsync(urls[i]));
}
}
- 54. for Loop
function (urls) {
for (var i = 0; i < urls.length; i++) {
$await(requestAsync(urls[i]));
}
} function (urls) {
var _b_ = Jscex.builders["async"];
return _b_.Start(this,
_b_.Delay(function () {
var i = 0;
return _b_.Loop(
function () { return i < urls.length; },
function () { i++; },
_b_.Delay(function () {
return _b_.Bind(requestAsync(urls[i]), function () {
return _b_.Normal();
});
}),
false
);
})
);
}
- 55. for
function (urls) {
var requests = [];
for (var i = 0; i < urls.length; i++) {
requests.push(requestAsync(urls[i]));
}
$await(Jscex.Async.parallel(requests));
}
- 56. for
function (urls) {
var requests = [];
for (var i = 0; i < urls.length; i++) {
requests.push(requestAsync(urls[i]));
}
function (urls) {
var _b_ = Jscex.builders["async"];
$await(Jscex.Async.parallel(requests));
} return _b_.Start(this,
_b_.Delay(function () {
var requests = [];
for (var i = 0; i < urls.length; i++) {
requests.push(requestAsync(urls[i]));
}
return _b_.Bind(Jscex.Async.parallel(requests), function () {
return _b_.Normal();
});
})
);
}
- 57. • BSD
•
• https://github.com/JeffreyZhao/jscex
• http://www.sndacode.com/projects/jscex