- In my previous post we have introduced with ES6 generators.If you missed it you can use this link to read my previous post.This post is part2 where we will explore another ES6 Generator feature.
- The yield keyword is used by the Generator to return the current iterator object containing value and done property.We have already learnt about yield in my previous post.
- The yield keyword has another form and it is called as yield with star * operator(yield*).This yield* operator can be used to call Generator inside a Generator.It means we can combine multiple Generators.
- In this Demo, “We will learn about using yield* to combine multiple Generators”.
- To demonstrate generator we have created a project named ES6GeneratorDemoPart2 and Traceur runtime is installed using Bower.Two subdirectories dev and out is created.The dev directory contains ES6 code and out directory contains the converted JavaScript code.The JavaScript file dev/my-generator.js file contains ES6 code and out/my-generator.js file contains the converted JavaScript code.The following screenshot shows the project structure.
- We have created 3 generators FruitGenerator,VegetableGenerator and FoodGenerator.The FruitGenerator returns different fruit names using yield keyword.VegetableGenerator returns different vegetable name using yield keyword.The FoodGenerator returns food names like rice ,wheat and also includes the FruitGenerator and VegetableGenerator items using yield* keyword.The following code shows the dev/my-generator.js file with ES6 script for these generators.
var FruitGenerator = function*(){ yield "Apple"; yield "Orange"; yield "Grapes"; yield "Mango"; }; var VegetableGenerator = function*(){ yield "Potato"; yield "Carrot"; yield "tomato"; yield "beetroot"; }; var FoodGenerator = function*(){ yield "rice"; yield* FruitGenerator(); yield "Wheat"; yield* VegetableGenerator(); } var aFoodGenerator = FoodGenerator(), nextFood = aFoodGenerator.next(), messageElement = document.getElementById("message"); //next object has value and done property console.log(JSON.stringify(nextFood)); while(!nextFood.done){ var liElement = document.createElement('li'); liElement.innerText = nextFood.value; messageElement.appendChild(liElement); nextFood = aFoodGenerator.next(); }
- The complied code using Traceur compiler is present in out/my-generator.js file.The following code shows the content of out/my-generator.js file.
System.registerModule("../dev/my-generator.js", [], function() { "use strict"; var __moduleName = "../dev/my-generator.js"; var FruitGenerator = $traceurRuntime.initGeneratorFunction(function $__0() { return $traceurRuntime.createGeneratorInstance(function($ctx) { while (true) switch ($ctx.state) { case 0: $ctx.state = 2; return "Apple"; case 2: $ctx.maybeThrow(); $ctx.state = 4; break; case 4: $ctx.state = 6; return "Orange"; case 6: $ctx.maybeThrow(); $ctx.state = 8; break; case 8: $ctx.state = 10; return "Grapes"; case 10: $ctx.maybeThrow(); $ctx.state = 12; break; case 12: $ctx.state = 14; return "Mango"; case 14: $ctx.maybeThrow(); $ctx.state = -2; break; default: return $ctx.end(); } }, $__0, this); }); var VegetableGenerator = $traceurRuntime.initGeneratorFunction(function $__1() { return $traceurRuntime.createGeneratorInstance(function($ctx) { while (true) switch ($ctx.state) { case 0: $ctx.state = 2; return "Potato"; case 2: $ctx.maybeThrow(); $ctx.state = 4; break; case 4: $ctx.state = 6; return "Carrot"; case 6: $ctx.maybeThrow(); $ctx.state = 8; break; case 8: $ctx.state = 10; return "tomato"; case 10: $ctx.maybeThrow(); $ctx.state = 12; break; case 12: $ctx.state = 14; return "beetroot"; case 14: $ctx.maybeThrow(); $ctx.state = -2; break; default: return $ctx.end(); } }, $__1, this); }); var FoodGenerator = $traceurRuntime.initGeneratorFunction(function $__2() { var $__3, $__4, $__5, $__6; return $traceurRuntime.createGeneratorInstance(function($ctx) { while (true) switch ($ctx.state) { case 0: $ctx.state = 2; return "rice"; case 2: $ctx.maybeThrow(); $ctx.state = 4; break; case 4: $__3 = $ctx.wrapYieldStar(FruitGenerator()[Symbol.iterator]()); $ctx.sent = void 0; $ctx.action = 'next'; $ctx.state = 16; break; case 16: $__4 = $__3[$ctx.action]($ctx.sentIgnoreThrow); $ctx.state = 13; break; case 13: $ctx.state = ($__4.done) ? 7 : 6; break; case 7: $ctx.sent = $__4.value; $ctx.state = 14; break; case 6: $ctx.state = 16; return $__4.value; case 14: $ctx.state = 18; return "Wheat"; case 18: $ctx.maybeThrow(); $ctx.state = 20; break; case 20: $__5 = $ctx.wrapYieldStar(VegetableGenerator()[Symbol.iterator]()); $ctx.sent = void 0; $ctx.action = 'next'; $ctx.state = 32; break; case 32: $__6 = $__5[$ctx.action]($ctx.sentIgnoreThrow); $ctx.state = 29; break; case 29: $ctx.state = ($__6.done) ? 23 : 22; break; case 23: $ctx.sent = $__6.value; $ctx.state = -2; break; case 22: $ctx.state = 32; return $__6.value; default: return $ctx.end(); } }, $__2, this); }); var aFoodGenerator = FoodGenerator(), nextFood = aFoodGenerator.next(), messageElement = document.getElementById("message"); console.log(JSON.stringify(nextFood)); while (!nextFood.done) { var liElement = document.createElement('li'); liElement.innerText = nextFood.value; messageElement.appendChild(liElement); nextFood = aFoodGenerator.next(); } return {}; }); System.get("../dev/my-generator.js" + '');
- These generators are used in demo.html file.The following code shows the content of demo.html file.
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>Understanding ES6 generator using Traceur Part 2 </title> <script src="bower_components/traceur-runtime/traceur-runtime.min.js"></script> </head> <body> <ol id="message"></ol> <script src="out/my-generator.js"></script> </body> </html>
- The output of the demo can be found in the following screenshot.
- The demo code can be downloaded from the following link: