JavaScript Generators are special kinds of functions that return a Generator object. They are treated as a iterator and thus means you are allowed to loop through them like arrays.

function* myGenerator() {
  yield 1
  yield 2
}

for (const num of myGenerator()) {
  console.log(num)
}

Generator functions are denoted by the * postfix after the function declaration and their usage of the yield keyword. I don't find myself using generators a lot in my day-to-day deving, but when I do, I always seem to have fun using these clever bits of code.

One example of a use-case for generator functions are for syncing data from an external API.

async function* fetchAll() {
  let page = 1
  let running = true
  
  while (running) {
    const res = await fetch(`someapi.com/products?page=${page}`)
    if(!res.ok) return
    const items = await res.json()
    for (const item of items) {
      yield item
    }
  }
}

for await (const item of fetchAll()) {
  syncToDatabase(item)
}

The above code sample will fetch all the products from someapi.com and sync them to the database. It will continue to fetch and yield items until the response results in an error code (such as a 404 for no items found). You'll also notice that Generators can be async, which results in a AsyncGenerator. These behave similar to regular generators but are allowed to have async executions inside of them.