Google Chromeã«å ¥ã£ãã¸ã§ãã¬ã¼ã¿ã¨Promiseã§éåæå¦çã«é©å½ãèµ·ãã
Google Chrome Canaryï¼æ£ç¢ºã«ã¯V8ï¼ã«ãã¤ãã«Generatorsï¼yieldï¼ãå ¥ã£ãããããä¸æã«ä½¿ãã¨ãã¨ã©ã¼å¦çãå«ãéåæã³ã¼ããåæçã«æ¸ããã¨ãã§ããããã«ãªããè¦éãã極ãã¦è¯ããªãã®ã§ãããã§ç´¹ä»ããã
ããã§ç´¹ä»ãããã®ã¯ãããNode.jsã§ã使ç¨ã§ããããã«ãªãã®ã§ãWebã¨ã®äºææ§ãæ°ã«ããå¿ è¦ã®ãªãNode.jsã§ã¯è¿ããã¡ã«æ´»ç¨ã§ããããã«ãªãã¨æãã
ä¸ã®ã³ã¼ããåããããã«ã¯ãææ°ã®Google Chrome Canaryã§ãchrome://flagsããexperimental javascriptãæå¹ã«ãã¦ããå¿ è¦ãããã
ES6 Harmonyã®Generatoræ§æã«ã¤ãã¦
functionã§ã¯ãªãfunction*ã¨ãããã¼ã¯ã¼ãã使ãã¨ãyieldãã¼ã¯ã¼ãã使ããããã«ãªãã
function* range(begin, end) { for (var i = begin; i < end; i++) { yield i; } }
ãããã¦ä½æããã¸ã§ãã¬ã¼ã¿ã¯ãfor ofæ§æã使ã£ã¦ã
for (var n of range(0, 5)) { console.log(n); }
ã¨ãã¦ä½¿ããã¨ãã§ããããä»ã®ã¨ããfor ofæ§æã¯å®è£ ããã¦ããªããããªã®ã§ãã¾ã 使ããªãã æåã§ã¸ã§ãã¬ã¼ã¿ãåãããã¨ãã§ããnext/send/throwã¡ã½ããã使ã£ã¦ã
var g = range(0, 2); console.log(g.next()); console.log(g.next()); console.log(g.next()); console.log(g.next()); // Error: Generator has already finished
ãã®ããã«åãããã¨ãã§ãããããã¯å®è£ æ¸ã¿ãsend/throwã¯å¼æ°ãä¸ã¤åãä»ãããããããyieldãè¿ãå¤ãæå®ããã¨ããyieldã«ä¾å¤ãçºçããããã¨ãã«ä½¿ãã 詳ããä»æ§ã¯ http://wiki.ecmascript.org/doku.php?id=harmony:generators ã«è¼ã£ã¦ããããã¾ãPythonã®ã¸ã§ãã¬ã¼ã¿ã¨ã»ã¨ãã©åãã¨æãã¨è¯ãã ããã
éåæå¦ç/Promiseã¨ã®çµã¿åãã
ã¸ã§ãã¬ã¼ã¿ã®ãããã¨ããã¯ãé¢æ°ãéä¸ã§æ¢ããããã¨ããã§ããããã®ç¹æ§ã¨ãPromiseããçµã¿åãããã¨ãéåæå¦çãåæçã«æ¸ããã¨ãã§ããã Promiseãã®ãã®ã®è©³ç´°ã«ã¤ãã¦ã¯ http://javascripter.hatenablog.com/entry/2012/12/30/232842 ã«æ¸ããã
ããã§ã¯Promiseã®å®è£ ã¨ãã¦jQuery.Deferredã使ããã好ããªãã®ã使ãã¨è¯ãã ããã ã¯ã¦ãã§ææãããã®ã§Promiseãä¿®æ£ id:teppeis ++
// new Promise(function (resolve, reject) { resolve('hi'); }) -> promise function Promise(setup) { var d = jQuery.Deferred(); var p = d.promise(); setup(d.resolve, d.reject); return p; }
ã¾ããå¾ã«å®ç¾©ããasyncé¢æ°ã使ãã¨ä½ãã§ããããå ã«ç¤ºãã ä¸çªç°¡åãªä¾ã ã¨ã
function wait(ms) { return new Promise(function (resolve, reject) { setTimeout(resolve, ms); }); } async(function* () { console.log('hi'); yield wait(1000); console.log('this will appear after 1 sec'); });
ã¾ããwaitãåæçã«æ¸ããã®ãããããããã¯ã¸ã§ãã¬ã¼ã¿ã使ããªãã¨
console.log('hi'); wait(1000).then(function () { console.log('this will appear after 1 sec'); });
ã§ããã
Promiseã®çµæãåå¾ãããã¨ãã§ããéåæXMLHttpRequestã¯ä¸è¨ã®ããã«æ¸ããã
function get(url) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', url, false); req.onload = function () { resolve(req); }; req.onerror = function () { reject(req); }; req.send(null); }); } async(function* () { var res = yield get(location.href); var len = res.responseText.length; console.log('length is', len); });
ããã¯ã¸ã§ãã¬ã¼ã¿æãã ã¨
get(location.href).then(function (res) { var len = res.responseText.length; console.log('length is', len); });
ã«å¯¾å¿ããã then(resolve, reject)ã®rejecté¨ã¯ã©ãæ¸ãã°ããã®ã ãããï¼åæå¦çã¨åãããã«
async(function* () { try { yield get(location.href); } catch (ex) { alert('could not fetch ' + location.href); } });
ã¨æ¸ãã°ãããasyncã¯ãããã¹ãè¿ãã®ã§
async(function* () { yield get(location.href); }).then(function () {}, function (ex) { // ã¨ã©ã¼å¦çã¯ãã㧠});
ã¨ãããã¨ãã§ããããå®éã®ã¨ãããyield promiseã¨ããã ãã§å®å ¨ã«åæå¦çã®ããã«æ±ããã
var len = async(function* () { ãreturn (yield get(location.href)).responseText.length; }); async(function* () { return (yield len) + 1; }).then(function (val) { console.log(val); }, function () { console.log('ãã¶ãgetã§ã¨ã©ã¼ãçºçããæãããã'); });
ãªã©ã®çµã¿åããããæå¾ éãåãã ãã¦ãèå¿ã®asyncé¢æ°ã«ã¤ãã¦ã ãã
function isPromise(maybePromise) { return maybePromise && typeof maybePromise.then === 'function'; } function isStopIteration(maybeStopIteration) { // ugly, but works well return maybeStopIteration && ( typeof StopIteration === 'function' ? maybeStopIteration instanceof StopIteration : maybeStopIteration.message === 'Generator has already finished'); } function async(thunk) { return new Promise(function (resolve, reject) { var thread = thunk(); function proceed(method, result) { var returnValue; try { returnValue = thread[method](result); } catch (ex) { if (isStopIteration(ex)) { resolve(result); } else { reject(ex); } return; } if (isPromise(returnValue)) { returnValue.then(function (result) { proceed('send', result); }, function (result) { proceed('throw', result); }); } else { // silently proceed proceed('send', returnValue); } } proceed('send', null); }); }
ãã£ãããã ãã§ããã ã¸ã§ãã¬ã¼ã¿ã使ãåæçã«æ¸ããã³ã¼ããasyncãè¿ãæã«ã¯Promiseã«ãªããPromiseèªä½ãæ¡å¼µããå¿ è¦ããªããã¨ãåæ/éåæãã¾ãã¦ã»ã¼åãããã«æ¸ãããã¨ãNodeã®Domainã®ãããªãã¨ãasyncã§å²ãã ãã§ã§ãããã¨ãèããã¨ãé常ã«çãããã¨æãã
åè
https://github.com/mozilla/task.js å°ãoverkillãªæ°ãããããåãã³ã³ã»ããã®ãã®ãä¸å¹´åããæ´æ°ããã¦ãªãããã©ããªã£ãã®ããªï¼ã¨ããæãã¯å¤å°ããã
https://github.com/kriskowal/q Q.asyncãåããã¨ããããã¨ãã¦ããããStopIterationããªãã®ã§Google Chromeã§ã¯åãã¦ããªããããã対å¿ããã¨æãããã
ã³ã¼ãããããããã«ä¿®æ£ãããã¡ãªã¿ã«ãFirefoxã¯ããã¶ãåããGeneratorãå®è£ ãã¦ãã¦ãES6ã®æ§æã¨ã¯å¤å°ç°ãªãç¬èªä»æ§ã ããtask.jsã¯Firefoxã§åãããã«ä½ããã¦ããã®ã§ãèå³ããã£ããåããã¦ã¿ãã¨è¯ãã ããã