Shikloshi Shikloshi - 6 months ago 13
Javascript Question

ES6 Generators: input value for .next()

I'm following this awesome blog and there is a simple example of generators with sending a value for the

.next()
method:

var answers = [
`It is certain`, `It is decidedly so`, `Without a doubt`,
`Yes definitely`, `You may rely on it`, `As I see it, yes`,
`Most likely`, `Outlook good`, `Yes`, `Signs point to yes`,
`Reply hazy try again`, `Ask again later`, `Better not tell you now`,
`Cannot predict now`, `Concentrate and ask again`,
`Don't count on it`, `My reply is no`, `My sources say no`,
`Outlook not so good`, `Very doubtful`
]
function answer () {
return answers[Math.floor(Math.random() * answers.length)]
}

// The most relevant part
function* chat () {
while (true) {
let question = yield '[Genie] ' + answer()
console.log(question)
}
}


I really can't understand how this input will produce this output:

var g = chat()
g.next()
console.log(g.next('[Me] Will ES6 die a painful death?').value)
// <- '[Me] Will ES6 die a painful death?'
// <- '[Genie] My sources say no'


Where does the first output comes from - the [Me] part of the result?

Answer

The expression after yield will go out(returned). The value passed to next() goes in, and the yield expression evaluates to this value. Note though any value passed in on the first .next() call is thrown away and not used.

  1. g.next() is called

    let question = yield '[Genie] ' + answer()    
                         ^-------------------^
          execution is paused here, this expression is evaluated
          and the result will go out(returned)
               {value:"[Genie] ...",done:false}
    
  2. Then g.next('[Me] Will ES6 die a painful death?') is called

    g.next('[Me] Will ES6 die a painful death?').value
           ^----------------------------------^
     string goes in, execution continues, yield expression 
          will be evaluated as the passed in string
    
     let question = yield '[Genie] ' + answer(); //becomes -v
     let question = '[Me] Will ES6 die a painful death?';
    
  3. question equals the [Me] string

  4. question gets logged to console by console.log(question)
  5. Execution continues until the next yield is encountered

    let question = yield '[Genie] ' + answer()    
                         ^-------------------^
          execution is paused here, this expression is evaluated
          and the result will go out(returned)
               {value:"[Genie] ...",done:false}
    
  6. Now g.next('[Me] Will ES6 die a painful death?') evaluates to

    {value:"[Genie] ...",done:false}
    

    Making the last line evaluating as such:

    console.log( g.next('[Me] Will ES6 die a painful death?').value );
    //becomes 
    console.log( ({value:"[Genie] ...",done:false}).value );
    //which becomes
    console.log("[Genie] ...");