ÔÚ¡¶ÉîÈëdz³öNode.js¡·µÄµÚ4ÕÂÀ±ÊÕßÉîÈëµØ½éÉÜÁ˵±Ç°Ê¢ÐÐÔÚNodeºÍǰ¶ËJavaScriptÖеļ¸ÖÖÒì²½±à³ÌµÄ½â¾ö·½°¸£¬Î¨¶À¶ÔGeneratorµÄ½â¾ö·½°¸Ã»ÓнéÉÜ¡£µ«Ëæ×ÅNode°æ±¾µÄÉý¼¶ºÍECMAScript
harmonyµÄÌØÐÔ²»¶ÏµÃµ½Ö§³Ö£¬ÔÚ0.11°æ±¾ÖУ¬ÎÒÃÇ¿ÉÒÔͨ¹ýÆôÓÃ--harmory²ÎÊýÈÃV8Ö§³ÖGenerator¡£×î½üConnect/Express±³ºóµÄ¿ª·¢ÍŶÓÒ²½«¾«Á¦×ªÒƵ½ÐµĿâºÍ¿ò¼ÜÉÏ£¬Õâ¸öºËÐÄ¿âºÍ¿ò¼Ü¾ÍÊÇcoºÍkoa£¬ËüÃÇ×îÖ÷ÒªµÄÌØµãÖ÷Òª¾ÍÊÇ»ùÓÚECMAScript
harmonyÖеÄGeneratorÌØÐÔ£¬ÕâʹµÃËüÔÚÒì²½±à³Ì·½ÃæÓнÏÓÅÑŵÄʵÏÖ¡£
±¾ÎĽ«Éî¶È½éÉÜÏÂGeneratorÊÇÈçºÎʵÏÖ½«Òì²½±à³Ì´ÓÔʼµÄǶÌ×ʽ´úÂëת»»³É±âƽµÄ˳Ðòʽ´úÂë¡£
Òì²½±à³ÌÎÊÌâ»Ø¹Ë
¼òµ¥µØ»Ø¹ËÏ£¬Òì²½±à³ÌµÄÎÊÌâÖ÷ÒªÓÐÁ½¸ö£ºÒ»¸öÊDZØÐëͨ¹ý»Øµ÷º¯Êý½øÐзµ»ØÖµµÄ´¦Àí£¬ÁíÒ»¸öÊǸ´ÔÓÇé¿öÏ»áÔì³ÉǶÌ×¹ýÉî¡£ÏÂÃæ¼òµ¥µÄ¸ø³öÁ½ÖÖµäÐ͵ÄÒì²½³¡¾°¡£
Òì²½´®ÐжÁÈ¡Îļþ£º
fs.readFile('file1.txt', 'utf8', function (err, txt) { if (err) { throw err; } fs.readFile(txt, 'utf8', function (err, content) { if (err) { throw err; } console.log(content); }); }); |
Òì²½²¢ÐжÁÈ¡Îļþ£º
fs.readFile('file1.txt', 'utf8', function (err, txt) { if (err) { throw err; } console.log(txt); }); fs.readFile('file2.txt', 'utf8', function (err, content) { if (err) { throw err; } console.log(content); }); |
ÉÏÊöÁ½ÖÖ³¡¾°Ï£¬¿ÉÒÔ¿´µ½´®ÐÐʱÓÉÓÚ´úÂëǶÌ×£¬µ÷ÓÃÔ½¶à£¬»áÔì³É´úÂëÔ½Ôã¸â¡£¶ÔÓÚÒì²½²¢ÐжÁÈ¡ÎļþµÄ´úÂ룬ÄѵãÊÇÎÞ·¨»ñÖª²¢ÐÐÒì²½µ÷ÓÃÍêÈ«Íê³ÉµÄʱ¼äµã£¬Òª½â¾öÕâ¸öÎÊÌâÐèÒª½èÖú¸÷ÖÖÒì²½Á÷³Ì¿â¡£
Ŀǰ½â¾öÒì²½Á÷³Ì¿ØÖÆÎÊÌâµÄÖ÷Á÷·½°¸ÓÐÒÔÏÂÈýÖÖ£º
1.×Ô¶¨Òåʼþʽ·½°¸
2.Promise/Deferred
3.¸ß½×º¯Êý´Û¸Ä»Øµ÷º¯Êý
ÓÉÓÚÔÚ¡¶Òì²½±à³Ì¡·Õ½ÚÖÐÒѾ³ä·Ö½éÉÜÁËÉÏÊöÈýÖÖ·½Ê½µÄʵÏÖÐÎʽ£¬ÕâÀï²»ÔÙÏêϸչ¿ªÈýÖÖ·½Ê½µÄϸ½Ú¡£µ«ÊÇΪÁËÐÐÎijÐǰÆôºó£¬ÕâÀï¼òµ¥»Ø¹ËϵÚÈýÖÖ·½°¸µÄʵÏÖ¡£
¸ß½×º¯ÊýÔÚÒì²½±à³ÌÖеÄʹÓÃ
¸ß½×º¯ÊýÔÚÒì²½±à³ÌÖеÄʹÓã¬×î¹ã·º¡¢×îÖªÃûµÄιýÓÚasyncºÍstepÕâÁ½¸ö¿â£¬Ëü½«Óû§Õý³£´«µÝ½øÀ´µÄ»Øµ÷º¯ÊýÌæ»»³É×Ô¼º°ü×°ÁËÌØÊâÂß¼µÄº¯Êý£¬È»ºóÔÙ´«µÝ¸øÒì²½µ÷Óᣵ±Òì²½µ÷ÓýáÊøºó£¬ÏÈÖ´ÐеÄÊÇÌØÊâÂß¼£¬È»ºó²ÅÊÇÓû§´«ÈëµÄ»Øµ÷º¯Êý¡£ÒÔÒ»¸ö¼òµ¥µÄ³¡¾°ÎªÀý£¬¼ÙÉèÐèÒªµÈ´ýËùÓÐÒì²½»Øµ÷Ö´ÐÐÍê³Éºó£¬²ÅÄÜÖ´ÐÐij¸öÂß¼£¬Õâʱͨ¹ý¸ß½×º¯Êý´Û¸Ä»Øµ÷º¯ÊýµÄ·½Ê½¾Í´óΪÊÜÓã¬Ò²Ï൱¼òµ¥¡£ÒÔÏÂΪ¼òµ¥ÊµÏÖ£º
var pending = (function () { var count = 0; return function (callback) { count++; return function () { count--; if (count === 0) { callback(); } }; }; }());
var done = pending(function () {
console.log('all is over');
});
fs.readFile('file1.txt', 'utf8', done());
fs.readFile('file2.txt', 'utf8', done()); |
ÉÏÊö´úÂëÖУ¬doneÖ´ÐÐÁËÁ½´Î£¬Ã¿´ÎÖ´ÐеĹý³ÌÖУ¬½«¼ÆÊýÆ÷count¼ÓÒ»£¬È»ºó·µ»ØÒ»¸öº¯Êý¡£µ±fs.readFileÕâ¸öÒì²½µ÷ÓýáÊøºó£¬doneÖ´ÐкóµÄ»Øµ÷º¯Êý»áµÃµ½Ö´ÐУ¬¼ÆÊýÆ÷¼õÒ»¡£µ±¼ÆÊýÆ÷»Øµ½0µÄʱºò£¬Òâζ×Ŷà¸öÒì²½µ÷ÓõĻص÷º¯Êý¶¼ÒѾִÐУ¬´ËʱִÐд«ÈëµÄ»Øµ÷º¯Êý¡£ÒòΪ·Ç×èÈûµÄÔÒò£¬done()Éú³ÉµÄº¯Êý²»»áÁ¢¼´Ö´ÐУ¬Ê¹µÃ¼ÆÊýÆ÷¿ÉÒÔÕý³£µØÔö¼ÓÖµ£¬½áÊøºó²ÅÂýÂý¼õÉÙÖµ¡£
Å׿ªÒì²½µ÷Óò»Ì¸£¬¸ß½×º¯ÊýµÄÊÔÓÃÉÏ£¬ÒªÈÃÓû§´«ÈëµÄº¯ÊýÄܵõ½Ö´ÐС£ÐèÒªÈçÏÂÕâÖÖ·½Ê½µÄµ÷Óãº
var done = pending(function () { console.log('all is over'); });
done()(); |
ÕâÀïÉú³ÉµÄº¯Êý±»Á¢¼´µ÷ÓÃÁË£¬countÕâ¸ö¼ÆÊýÆ÷¼ÓÒ»ºó£¬Á¢¼´¼õÒ»£¬È»ºó´¥·¢µÈÓÚÁãµÄÌõ¼þ£¬ÓÚÊǻص÷º¯Êý±»Ö´ÐÐÁË¡£
ÔÚͨ¹ýGenerator½â¾öÒì²½±à³ÌÎÊÌâµÄ·½°¸ÖУ¬¸ß½×º¯ÊýÓëGeneratorÖ®¼ä»á²úÉúÏ൱΢ÃîµÄ»¯Ñ§·´Ó¦¡£
Generatorɨä
GeneratorµÄÖÐÎÄ·ÒëÊÇÉú³ÉÆ÷£¬ËüÊÇECMAScript6£¨´úºÅharmory£©ÖÐÌṩµÄÐÂÌØÐÔ¡£ÔÚ¹ýÈ¥£¬·â×°Ò»¶ÎÔËËãÂß¼µÄµ¥ÔªÊǺ¯Êý¡£º¯ÊýÖ»´æÔÚ¡°Ã»Óб»µ÷Óá±»òÕß¡°±»µ÷Óá±µÄÇé¿ö£¬²»´æÔÚÒ»¸öº¯Êý±»Ö´ÐÐÖ®ºó»¹ÄÜÔÝÍ£µÄÇé¿ö£¬¶øGeneratorµÄ³öÏÖÈÃÕâÖÖÇé¿ö³ÉΪ¿ÉÄÜ¡£
GeneratorµÄ¶¨Òå
GeneratorµÄ¶¨ÒåÊ®·Ö¼òµ¥£¬ÓëÆÕͨµÄº¯ÊýÏà±È£¬ËüÖ»¶à³öÒ»¸ö*ºÅ¡£ÒÔÏÂΪ¼òµ¥Àý×Ó£º
var compute = function* (a, b) { var sum = a + b; console.log(sum); var c = a - b; console.log(c); var d = a * b; console.log(d); var e = a / b; console.log(e); }; |
Õâ¸öÐǺÅÖ»Òª³öÏÖÔڹؼü×ÖfunctionºÍº¯ÊýÃûÖ®¼ä¼´¿É¡£Èç¹ûÊÇÄäÃûº¯Êý£¬³öÏÖÔÚfunctionºÍ²ÎÊýÁбíµÄÆðʼÀ¨ºÅÖ®¼ä¼´¿É¡£
¶¨ÒåµÄGeneratorʵ¼ÊÉÏ¿ÉÒÔÀí½âΪ¶¨ÒåÁËÒ»ÖÖÌØÊâµÄÊý¾Ý½á¹¹£¬ÒªµÃµ½GeneratorʵÀý£¬»¹ÐèÒªÖ´ÐÐËüÒ»´Î£º
var generator = compute(4, 2); |
ÕâÑùÎÒÃÇÄܵõ½Ò»¸öGenerator¶ÔÏó¡£Generator¶ÔÏó¾ßÓÐÒ»¸önext·½·¨¡£ÒªÊ¹µÃ¶¨ÒåÖзâ×°µÄ´úÂëÂß¼µÃµ½Ö´ÐУ¬»¹µÃÐèÒªµ÷ÓÃÒ»´Înext·½·¨²ÅÐС£
µ÷ÓÃÖ®ºóµÄÊä³ö½á¹ûÈçÏ£º
$ node --harmony-generators examples/compute.js 6 2 8 2 |
yield¹Ø¼ü×Ö
µ¥¶ÀµØ½éÉÜGeneratorûÓÐÌ«´ó¼ÛÖµ£¬ÒòΪËü³ýÁ˸ü¸´ÔÓÍ⣬¹¦ÄÜÓëÆÕͨº¯ÊýûÓÐÌ«´ó²î±ð¡£ÕæÕýÈÃGenerator¾ßÓмÛÖµµÄÊÇyield¹Ø¼ü×Ö£¬Õâ¸öyield¹Ø¼ü×ÖÈÃGeneratorÄÚ²¿µÄÂß¼Äܹ»Çиî³É¶à¸ö²¿·Ö¡£ÏÂÃæÊǼòµ¥µÄʾÀý£º
var compute = function* (a, b) { var sum = a + b; yield console.log(sum); var c = a - b; yield console.log(c); var d = a * b; yield console.log(d); var e = a / b; console.log(e); }; |
¼ÓÈëyield¹Ø¼ü×Öºó£¬ÎÒÃǼÌÐø½«ÆäʵÀý»¯£¬È»ºóµ÷ÓÃ.next()·½·¨£º
var generator = compute(4, 2); generator.next(); |
¿ÉÒÔ¿´µ½Êä³öÈçÏ£º
$ node --harmony-generators examples/compute.js 6 |
ÉÏÃæµÄÊä³öÒâζ×Å´úÂëÖ´Ðе½µÚÒ»¸öyield¹Ø¼ü×ÖµÄʱºò¾ÍÍ£Ö¹ÁË¡£ÒªÈÃÒµÎñÂß¼¼ÌÐøÖ´ÐÐÍ꣬ÐèÒª·´¸´µ÷ÓÃ.next()¡£
var generator = compute(4, 2); generator.next(); // 6 generator.next(); // 2 generator.next(); // 8 generator.next(); // 2 |
¿ÉÒÔ¼òµ¥µØÀí½âΪyield¹Ø¼ü×Ö½«³ÌÐòÂß¼»®·Ö³É¼¸²¿·Ö£¬Ã¿´Î.next()Ö´ÐÐʱִÐÐÒ»²¿·Ö¡£ÕâʹµÃ³ÌÐòµÄÖ´Ðе¥ÔªÔÙÒ²²»ÊǺ¯Êý£¬¸´ÔÓµÄÂß¼¿ÉÒÔͨ¹ýyieldÀ´ÔÝÍ£¡£´ÓÆÓËØµÄ½Ç¶ÈÀ´¿´£¬ÕâÀàËÆÓÚ½«Ò»¸öº¯ÊýµÄÂß¼·Ö²ðΪËĸöº¯Êý£¬µ«ËüÃǹ²ÏíÉÏÏÂÎÄ¡£
yield³ýÁËÇиîÂß¼Í⣬ËüÓë.next()µÄÐÐΪϢϢÏà¹Ø¡£Ã¿´Î.next()µ÷ÓÃʱ£¬·µ»ØÒ»¸ö¶ÔÏó£¬Õâ¸ö¶ÔÏó¾ß±¸Á½¸öÊôÐÔ£¬ÆäÖÐÒ»¸öÊôÐÔÊDz¼¶ûÐ͵Ädone¡£Ëü±íʾÕâ¸öGenerator¶ÔÏóµÄÂß¼¿éÊÇ·ñÖ´ÐÐÍê³É¡£ÁíÒ»¸öÊôÐÔÊÇvalue£¬ËüÀ´×ÔÓÚyieldÓï¾äºóµÄ±í´ïʽµÄ½á¹û¡£ÎÒÃǽ«´úÂë¼òµ¥Ð޸ģ¬¿ÉÒÔ¿´µ½Ð§¹û£º
var compute = function* (a, b) { var sum = a + b; yield sum; var c = a - b; yield c; var d = a * b; yield d; var e = a / b; return e; }; var generator = compute(4, 2); console.log(generator.next()); // { value: 6, done: false } console.log(generator.next()); // { value: 2, done: false } console.log(generator.next()); // { value: 8, done: false } console.log(generator.next()); // { value: 2, done: true } |
ÉÏÊöÊÇyield¶Ô.next()ÐÐΪµÄÓ°Ï죬·´Ö®£¬.next()Ò²ÄÜÓ°Ïìµ½yield¡£¿ÉÒÔ¼òµ¥µØ²Â²âÏÂÈçÏ´úÂëÖлá´òÓ¡³öʲô½á¹û£º
var compute = function* (a, b) { var foo = yield a + b; console.log(foo); }; |
Ò²Ðí¶ÁÕß»áÒÔΪÊÇa + bµÄÖµ£¬µ«ÊÇÕâÀï²»ÊÇ£ºÄ¬ÈÏÇé¿öÏ£¬Õâ¸öfoo´òÓ¡³öÀ´ÊÇundefined¡£ÄÇô.next()ÈçºÎÓ°ÏìyieldµÄÄØ£¿´ð°¸ÔÚÓÚ¿ÉÒÔͨ¹ý.next()´«µÝ²ÎÊý£¬¸³Öµ¸øyield¹Ø¼ü×ÖÇ°ÃæµÄ±äÁ¿ÉùÃ÷¡£¼ûÏÂÃæµÄ¼òµ¥Ê¾Àý£º
var compute = function* (a, b) { var foo = yield a + b; console.log(foo); };
var generator = compute(4, 2);
generator.next();
generator.next("Hello world!"); // Hello
world! |
ËùÒÔ£¬¶ÔÓÚGenerator¶øÑÔ£¬Ëü²»½ö¿ÉÒÔ½«Âß¼µÄµ¥ÔªÇзֵøüϸÍ⣬»¹ÄÜÔÚÔÝÍ£ºÍ¼ÌÐøÖ´Ðеļä¸ôÖУ¬¶¯Ì¬´«ÈëÊý¾Ý£¬Ê¹µÃ´úÂëÂß¼¿ÉÒÔ¸üÁé»î¡£Ïà±ÈÆÕͨº¯Êý£¬GeneratorµÄÌØÐÔÏ൱ÁîÈËÆÚ´ý¡£
GeneratorÓëÒì²½±à³Ì
³õ¼û֮ϣ¬GeneratorËÆºõÓëÒì²½±à³ÌÖ®¼ä»¹°Ë¸Í×Ó´ò²»×Å¡£µ«Ç°Îĵĸ߽׺¯ÊýºÍGeneratorµÄ½éÉÜÒѾΪÎÒÃÇ×¼±¸ºÃÁË»ù´¡¡£ÎÒÃǼÌÐø½Ò¿ªGeneratorÊÇÈçºÎÓëÒì²½±à³ÌĦ²Á³öÉÁÁÁµÄ»ð»¨µÄ¡£
ÔÚÓµÓÐÁËyield¹Ø¼ü×Öºó£¬ÎÒÃÇ¿ÉÒÔºÜÇÉÃîµØ´¦ÀíÒì²½µ÷ÓõĻص÷º¯Êý¡£ÒÔ˳Ðò¶ÁÈ¡Á½¸öÎļþµÄ³¡¾°ÎªÀý£º
fs.readFile('file1.txt', 'utf8', function (err, txt) { if (err) { throw err; } fs.readFile(txt, 'utf8', function (err, content) { if (err) { throw err; } console.log(content); }); }); |
Èç¹ûÎÒÃÇÒªÍê³ÉÕâÁ½¸ö²Ù×÷£¬¶øÇÒ²»ÒÔǶÌ׵ķ½Ê½½øÐУ¬ÎÒÃÇ¿ÉÒÔºÜ×ÔÈ»Ïëµ½ÒÔyieldÀ´·Ö¸îÁ½¸ö²Ù×÷¡£
var flow = function* () { var txt = yield fs.readFile('file1.txt', 'utf8'); var content = yield fs.readFile(txt, 'utf8'); console.log(content); }; |
ÕâÀïËäȻûÓÐдÈë»Øµ÷º¯Êý£¬µ«ÎÒÃÇ¿ÉÒÔÏëÏó£¬Èç¹û»Øµ÷º¯ÊýÖ´ÐеÄʱºò´¥·¢Õâ¸öGeneratorÖ´ÐÐÒ»´Î.next()£¬È»ºó½«·µ»Ø½á¹ûͨ¹ý.next(result)ÕâÑùµÄÐÎʽ´«È룬ÕâÑù¾¡¹ÜÊÇÒì²½µ÷Ó㬵«´úÂë±àдÐÎʽÒѾ½üºõ˳ÐòʽÁË¡£
ÏëÏóÊÇÃÀºÃµÄ£¬ÏÖʵÄÜ·ñʵÏÖÊÇÁíÒ»»ØÊ¡£ÒªÍê³ÉÉÏÃæµÄÄ¿µÄ£¬ÐèÒª×öµÄÊÂÇéÓÐÁ½²½£º
1.ÐèÒªÔڻص÷º¯ÊýÖÐÖÃÈëÂß¼£¬ÓÃÓÚÊÕ¼¯»Øµ÷º¯Êý´«µÝµÄÊý¾Ý¡£
2.ͨ¹ý.next()´«ÈëÒì²½Ö´ÐеĽá¹û£¬´«µÝ¸øyield£¬ÈÃÒµÎñÁ÷³Ì¼ÌÐø½øÐС£
¸ÄÔìÒì²½·½·¨
ΪÁËÍê³ÉÊÕ¼¯Òì²½µ÷ÓõĽá¹ûÊý¾Ý£¬ÎÒÃDZØÐëµÃ½èÖú¸ß½×º¯Êý¡£ÈçÏÂÊÇÒ»¸öÐ޸Ļص÷º¯ÊýÂß¼µÄº¯Êý£º
var helper = function (fn) { return function () { var args = [].slice.call(arguments); var pass; args.push(function () { // Ôڻص÷º¯ÊýÖÐÖ²ÈëÊÕ¼¯Âß¼ if (pass) { pass.apply(null, arguments); } }); fn.apply(null, args);
return function (fn) { // ´«ÈëÒ»¸öÊÕ¼¯º¯Êý
pass = fn;
};
};
}; |
Õâ¸öº¯ÊýµÄ²ÎÊýÊÇÒ»¸öÒì²½µ÷Óú¯Êý£¬µ÷ÓÃÖ®ºó£¬µÃµ½Ò»¸öеĺ¯Êý£¬Õâ¸öº¯ÊýÔÚÖØÐÂÕûÀíÁ˲ÎÊýÁбíºó£¬Ìí¼ÓÁËÒ»¸öʵ¼Ê±»µ÷Óõ½µÄ»Øµ÷º¯Êý¡£Õâ¸öеĺ¯ÊýÖ´Ðк󣬻áµ÷ÓÃÕæÕýµÄÒì²½º¯Êý£¬È»ºóÔٴηµ»ØÒ»¸öº¯Êý£¬×îºó·µ»ØµÄº¯ÊýµÄ×÷ÓÃÊÇΪÁËËæÊ±×¢ÈëеÄÂß¼£¨pass£©¡£ÔÚ²ÎÊýÁбíºóÌí¼ÓµÄ»Øµ÷º¯ÊýÖУ¬Ëü»á½«½á¹û´«µÝ¸ø×îÖÕ¸øµ½µÄº¯Êý¡£
ÓÃÓïÑÔÀ´½âÊÍÕâ¶Î´úÂëÓеã³ÔÁ¦£¬ÎÒÃÇÒÔfs.readFileµ÷ÓÃΪʵ¼ÊÀý×Ó£¬Öصã²Î¼ûÏÂÎĵÄ×¢ÊÍ£º
var readFile = helper(fs.readFile); // => // function () { // var args = [].slice.call(arguments); // var pass; // args.push(function () { // Ôڻص÷º¯ÊýÖÐÖ²ÈëÊÕ¼¯Âß¼ // if (pass) { // pass.apply(null, arguments); // } // }); // fn.apply(null, args); // // return function (fn) { // ´«ÈëÒ»¸öÊÕ¼¯º¯Êý // pass = fn; // }; // }
var flow = function* () {
var txt = yield readFile('file1.txt', 'utf8');
console.log(txt);
};
var generator = flow();
var ret = generator.next(); // Ö´ÐÐreadFile('file1.txt',
'utf8');
// ret.value =>
// function (fn) {
// pass = fn;
// } |
¿ÉÒÔ¿´µ½ÉÏÃæµÄ´úÂ룬ÎÒÃÇÒѾ³É¹¦µÄ½«flowÕâ¸öGeneratorµÄµÚÒ»²¿·Ö´úÂëÖ´ÐÐÆðÀ´£¬ÎÒÃÇ¿ÉÒÔͨ¹ýret.valueÀ´³¢ÊÔÖ²ÈëÒ»¶ÎÌØÊâµÄÂß¼£¬Í¬Ê±ÔÚÒì²½µ÷ÓýáÊøºó£¬½«Êý¾ÝÈ¡³ö£¬Í¬Ê±Ö´ÐÐGeneratorµÄÏÂÒ»²¿·ÖÂß¼¡£ÍêÕû´úÂëÈçÏ£º
var generator = flow(); var ret = generator.next(); // Ö´ÐÐreadFile('file1.txt', 'utf8'); ret.value(function (err, data) { if (err) { throw err; } generator.next(data); }); |
ͨ¹ýÕâÑùÖÃÈëÌØÊâÂß¼ºó£¬Ê¹µÃflowÖеĴúÂëÄܹ»°´ÆÚÍû˳ÀûÖ´ÐУ¬Í¨¹ýyieldÇÉÃîµØ½«»Øµ÷º¯ÊýµÃµ½µÄֵת»»ÎªÀàËÆ·µ»ØÖµ¡£
ΪÁËÈÃËùÓеÄGeneratorÄÜÊÊÓ¦ÕâÖÖÇé¿ö£¬ÎÒÃÇÉè¼ÆÒ»¸öÁ÷³Ì¿ØÖƺ¯Êý£¬ÓÃÀ´×¨ÃÅ¿ØÖÆ´ËÀà²Ù×÷¡£
Éè¼ÆÁ÷³Ì¿ØÖƺ¯Êý
ΪÁËÏòTJ´óÉñÖ¾´£¬Õâ¸öº¯ÊýÎÒÃÇÔÝʱÃüÃûΪco¡£ËüÒª½øÐеIJÙ×÷ÊÇÈÃGeneratorÆô¶¯£¬ÔÚGeneratorÔÝÍ£µÄʱºò£¬Ö²ÈëÂß¼¡£¼òµ¥ÊµÏÖÈçÏ£º
var co = function (flow) { var generator = flow(); var next = function (data) { var result = generator.next(data); if (!result.done) { result.value(function (err, data) { if (err) { throw err; } next(data); }); } }; next(); }; |
´úÂëÖÐͨ¹ýµÝ¹éµ÷ÓÃÀ´Íê³ÉGeneratorÖÐÁ÷³ÌµÄÖ´ÐУ¬µ÷ÓÃʾÀýÈçÏ£º
co(function* () { var txt = yield readFile('file1.txt', 'utf8'); console.log(txt); var txt2 = yield readFile('file2.txt', 'utf8'); console.log(txt2); }); |
Ö´Ðнá¹ûÈçÏ£º
$ node --harmony-generators flow.js I am file1. I am file2. |
Èç´ËÎÒÃǾÍÍê³É´ÓǶÌ׺¯ÊýµÄд·¨×ª»»ÎªË³ÐòʽµÄ±àд£¬Éî¶ÈǶÌ×´øÀ´µÄ¡°µØÓüÖ®ÃÅ¡±½«³ÉΪÀúÊ·¡£
²¢ÐÐÖ´ÐÐ
Ç°ÃæµÄÀý×ÓÖУ¬ÒѾ³É¹¦µØ½«Ç¶Ì×´úÂëת»»ÎªË³ÐòµÄ±âƽµÄ´úÂ룬µ«ÊÇÒì²½µ÷ÓÃÖ®¼äÈÔÈ»ÊÇ´®ÐÐÖ´ÐУ¬ÕâʹµÃÎÒÃÇÎÞ·¨ÏíÊܵ½NodeÖв¢ÐÐI/OµÄºÃ´¦¡£Îª´ËÎÒÃÇ»¹ÐèÒª¸Ä½øcoº¯Êý£¬Ê¹µÃÒì²½µ÷ÓÃÄܲ¢ÐÐÖ´ÐУ¬Í¬Ê±ÒÀ¾É±£Ö¤´úÂëµÄ˳Ðò¡£
Ϊ´Ë£¬ÎÒÃÇÔ¼¶¨µ±yieldºóµÄ±í´ïʽ½á¹ûÊÇÒ»¸öÊý×éʱ£¬±íʾÀïÃæÎª¶à¸öÒì²½µ÷Ó᣼òµ¥µÄÐÞ¸ÄÈçÏ£º
var co = function (flow) { var generator = flow(); var next = function (data) { var ret = generator.next(data); if (!ret.done) { if (Array.isArray(ret.value)) { var count = 0; var results = []; ret.value.forEach(function (item, index) { count++; item(function (err, data) { count--; if (err) { throw err; } results[index] = data; if (count === 0) { next(results); } }); }); } else { ret.value(function (err, data) { if (err) { throw err; } next(data); }); } } }; next(); }; |
µ÷ÓÃʾÀýÈçÏ£¬µ±ÎªÊý×éʱ£¬Ó¦µ±²¢ÐÐÖ´ÐУº
co(function* () { var results = yield [readFile('file1.txt', 'utf8'), readFile('file2.txt', 'utf8')]; console.log(results[0]); console.log(results[1]); var file3 = yield readFile('file3.txt', 'utf8'); console.log(file3); }); |
Ö´Ðнá¹ûÈçÏ£º
$ node --harmony-generators parallel.js
I am file1.
I am file2.
I am file3.
|
ΪÁËÑéÖ¤Òì²½µ÷ÓÃÊDz¢ÐнøÐеģ¬ÎÒÃÇ»»Óö¨Ê±Æ÷À´²âÊÔ£º
var _sleep = function (ms, fn) {
setTimeout(fn, ms);
};
var sleep = helper(_sleep);
co(function* () {
console.time('sleep1');
yield sleep(1000);
yield sleep(1000);
console.timeEnd('sleep1');
console.time('sleep2');
yield [sleep(1000), sleep(1000)];
console.timeEnd('sleep2');
}); |
Ö´Ðнá¹ûÈçÏ£º
$ node --harmony-generators sleep.js
sleep1: 2004ms
sleep2: 1005ms
|
´Ósleep2µÄÊä³öÀ´¿´£¬yield¹Ø¼ü×ÖºóµÄÊý×éÖеÄËùÓÐÒì²½µ÷Óõõ½²¢ÐÐÖ´ÐС£
С½á
ÖÁ´Ë£¬ÎÒÃÇС½áÒ»ÏÂͨ¹ýGenerator½øÐÐÁ÷³Ì¿ØÖƵöÒªµã¡£Ê×ÏÈ£¬Ã¿¸öÒì²½·½·¨¶¼ÐèÒª±ê×¼»¯Îªyield¹Ø¼ü×ÖÄܽÓÊܵķ½·¨£¬Ê¹ÎÒÃÇÓлú»á×¢ÈëÌØÊâÂß¼£¬Õâ¸ö¹ý³Ì±»TJ³ÆÎªthunkify¡£Æä´Î£¬ÐèÒªÇÉÃîµØ½«Òì²½µ÷ÓÃÖ´ÐÐÍê³ÉµÃµ½µÄ½á¹ûͨ¹ý.next()´«µÝ¸øÏÂÒ»¶ÎÁ÷³Ì¡£×îºó£¬ÐèÒªµÝ¹éµØ½«ÒµÎñÂß¼Ö´ÐÐÍê³É¡£
ÐèҪעÒâµÄÊÇyieldÖ»ÄÜÔÝÍ£GeneratorÄÚ²¿µÄÂß¼£¬Ëü²¢²»ÊÇÕæÕýÔÝÍ£Õû¸öỊ̈߳¬GeneratorÍâµÄÒµÎñÂß¼ÒÀÈ»»á¼ÌÐøÖ´ÐÐÏÂÈ¥¡£
ÏòϼæÈÝ
ÎÒÃÇÖªµÀGeneratorºÍyield¹Ø¼ü×ÖµÄÌØÐÔÀ´×ÔÓÚECMAScript6£¬ÕâÒâζ×ÅĿǰNodeÖ÷Á÷µÄ0.10°æ±¾ÉÏÎÞ·¨ÏíÊܵ½ÕâЩÁîÈ˼¤¶¯µÄÌØÐÔ£»ÁíÍ⣬GeneratorµÄÓï·¨ÓëÏÖÐеÄÓï·¨²»¼æÈÝ£¬µ¼ÖÂÎÞ·¨½øÐÐshimʽµÄ¼æÈÝ¡£µ«ÊÇÊÂÇéÒ²²¢²»¾ø¶Ô£¬ÕâЩÄÑÌâ²¢²»ÄÜÄѵ¹geekÃǷḻµÄÏëÏóÁ¦¡£À´×ÔFacebookµÄ¹¤³Ìʦ·¢²¼ÁËÒ»¸öregeneratorµÄ¹¤¾ß£¬Ëü½«ECMAScript6ÖеÄGeneratorºÍyieldÓï·¨ÖØÐ±àÒ룬ʹµÃ±àÒë³öµÄ´úÂëÄܹ»ÔÚECMAScript5ÏÂÖ´ÐУ¬Í¬Ê±´ïµ½ÏàͬµÄЧ¹û¡£
ÏÂÃæµÄ´úÂ룬ÎÒÃdz¢ÊÔͨ¹ýregenerator½øÐбàÒ룺
var flow = function* () { console.time('sleep1'); yield sleep(1000); yield sleep(1000); console.timeEnd('sleep1'); console.time('sleep2'); yield [sleep(1000), sleep(1000)]; console.timeEnd('sleep2'); }; |
½á¹ûÈçÏ£º
var flow = wrapGenerator.mark(function() { return wrapGenerator(function($ctx0) { while (1) switch ($ctx0.prev = $ctx0.next) { case 0: console.time('sleep1'); $ctx0.next = 3; return sleep(1000); case 3: $ctx0.next = 5; return sleep(1000); case 5: console.timeEnd('sleep1'); console.time('sleep2'); $ctx0.next = 9; return [sleep(1000), sleep(1000)]; case 9: console.timeEnd('sleep2'); case 10: case "end": return $ctx0.stop(); } }, this); }); |
Õâ¶Î´úÂëÖеÄwrapGenerator.markºÍwrapGeneratorÀ´×ÔÓÚregeneratorÉú³ÉµÄÒÀÀµÖУ¬ÓÉÓÚ´úÂëÌ«¶à£¬Ôݲ»¸ø³ö¡£ÈçÐè²é¿´£¬¿ÉÒÔ³¢ÊÔÒÔÏÂÃüÁî
$ regenerator -r generator.js |
Èç¹û±àдµÄÄ£¿éÏë¼æÈÝECMAScript5ºÍECMAScript6£¬¿ÉÒÔ³¢ÊÔͨ¹ýregeneratorÉú³ÉÁ½Ì×´úÂ룬ÔÚECMAScript5Ï£¬ÒýÈë±àÒëºóµÄ´úÂ룬ÔÚECMAScript6Ï£¬ÒýÈëGeneratorºÍyieldÓï·¨µÄ´úÂ롣ʾÀýÈçÏ£º
module.exports = supportES6 ? require('./lib/index.js') : require('./es5/index.js'); |
Èç¹ûÒªÖ±½ÓÌåÑéGeneratorµÄÌØÐÔ£¬¿ÉÒÔ³¢ÊÔ°²×°gnodeÕâ¸öÄ£¿é¡£ËüµÄÔÀíÔÚ0.11.xµÄ°æ±¾ÉÏÊÇÆôÓÃ--harmory-generators£¬ÔÚ0.10.xÏÂÔòÊǵ÷ÓÃregenerator½«´úÂë±àÒëΪECMAScript5Ö§³ÖµÄ´úÂ룬ȻºóÔÙÖ´ÐС£
×ܽá
GeneratorµÄ³öÏÖ£¬Ê¹µÃÁ÷³Ì¿ØÖÆ¿ÉÒÔ¸üϸÄ壬ͨ¹ýcoºÍsuspend¿â£¬ÎÒÃǼ¸ºõÒѾÍêȫʵÏÖÁËÁ÷³Ì¿ØÖƵÄÏßÐÔ´¦Àí£¬Í¬Ê±»¹ÄÜÏíÊܵ½²¢ÐÐÒì²½µÄÐÔÄÜÌáÉý£¬ÔÚ²»ËðʧÐÔÄܵÄÇé¿öÏ£¬´ó´óÌáÉýÁ˱à³ÌÌåÑé¡£¼òµ¥¶øÑÔ£¬¼´Ê¹Ö»ÎªÕâ¸öÌØÐÔ£¬ECMAScript6Ò²ÖµµÃÆÚ´ý¡£ |