Random memo

Generator iterator in javascript

October 10, 2018

In this post, I am trying to write code snippets about generator/iterator in javascript that explain themselves by running them. Key points are described in the comment area of code snippets.

It is written with texts barely enough for myself to refresh memory of technical concepts I have gotten through. My apologies in case you read this post and find it not useful.

Generator iterator

const generator = function*(init) {
  const foo = yield init + " one" // resume iterator with 'start one'.
  const bar = yield foo + " two"  // resume iterator with 'foo two'.
  const baz = foo + bar
  console.log("333", baz)
  return "the end"                // resume iteraotr with 'the end'
}

const iterator = generator("start")       // create iterator
console.log("111", iterator.next("lost")) // start generator
console.log("222", iterator.next("foo"))  // resume generator with 'foo'
console.log("444", iterator.next("bar"))  // resume generator with 'bar'
console.log("555", iterator.next("lost")) // generator already done

Output:

111 { value: 'start one', done: false }
222 { value: 'foo two', done: false }
333 foobar
444 { value: 'the end', done: true }
555 { value: undefined, done: true }

Generator handling asynchronous values

const asyncValue = (value, ms) =>
  new Promise((resolve, reject) => setTimeout(() => resolve(value), ms))

const generator = function*() {
  let a3 = yield asyncValue(3, 500)
  let a5 = yield asyncValue(5, 500)
  let a7 = yield asyncValue(7, 500)
  return a3 + a5 + a7
}

const iterator = generator()

// iterate and process Promises recursively
function handleAsyncValues(obj) {
  if (obj.done) {
    console.log("total =", obj.value)
  } else {
    obj.value.then(v => {
      handleAsyncValues(iterator.next(v))
    })
  }
}

handleAsyncValues(iterator.next())

console.log("------ End of code snippet ------")

Output:

------ End of code snippet ------
total = 15

Note that the order of log printing is asynchronous.

More interestingly, using async/await, funtion handleAsyncValues() in code snippet above can be replaced by async version below.

async function handleAsyncValues(obj) {
  if (obj.done) {
    console.log("total =", obj.value)
  } else {
    handleAsyncValues(iterator.next(await obj.value))
  }
}

and output result will be the same.


Sangche

Written by Sangche. Github