Search code examples
javascriptgeneratoryield

JavaScript: Setting value using yield in nested generators


function* test(action) {
    const subgenerator = function*() {
        const subgeneratorVariable = yield '1';
        console.log('subgeneratorVariable', subgeneratorVariable);
    };

    for (const generatedValue of subgenerator()) {
        const result = yield generatedValue;
        console.log('result', result);
    }
}
const gen = test();

console.log(gen.next());
console.log(gen.next('a'));

This returns:

{value: "1", done: false}
result a
subgeneratorVariable undefined
{value: undefined, done: true}

So I don't have access to yield results in the nested generator. However!

In this case:

function* test(action) {
    const subgenerator = function*() {
        const subgeneratorVariable = yield '1';
        console.log('subgeneratorVariable', subgeneratorVariable);
        const subgeneratorVariable2 = yield '2';
        console.log('subgeneratorVariable2', subgeneratorVariable2);
    };

    const result = yield* subgenerator();
    console.log('result', result);
}
const gen = test();

console.log(gen.next());
console.log(gen.next('1'));
console.log(gen.next('2'));

The result is:

{value: "1", done: false}
subgeneratorVariable a
{value: "2", done: false}
subgeneratorVariable2 b
result undefined
{value: undefined, done: true}

So the situation is reversed. Now I have access to yielded value ONLY in nested generator.

Is there any way of passing values/results between these two generators?


Solution

  • yield is going to return what you are passing to next as a parameter, not the expression at right side; for...of internally is calling next without parameters so you are getting undefined.

    Maybe this example helps you to understand with a do...while instead of for...of:

    function* test(action) {
        const subgenerator = function*() {
            let subgeneratorVariable;
    
            subgeneratorVariable = yield '1';  
            console.log("subgeneratorVariable: " + subgeneratorVariable);
    
            subgeneratorVariable = yield '2';  
            console.log("subgeneratorVariable: " + subgeneratorVariable);
        };
    
        const sub = subgenerator();
        let value;        
    
        do {
          value = yield sub.next(value).value;
          console.log("value: " + value);
        } while(value);
    }
    
    const gen = test();
    let value;
    
    value = gen.next().value;
    value = gen.next(value).value;
    value = gen.next(value).value;
    

    The result is:

    value: 1
    subgeneratorVariable: 1
    value: 2
    subgeneratorVariable: 2
    

    As you can see, if you want to keep the values between the generators you must pass the result values to the generators next function.