Generators

Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. (MDN)

Concurrency Control:

You can control the flow of asynchronous operations using generators. This is useful when you need to execute tasks in a specific order.

function* taskExecutor() {
  yield task1();
  yield task2();
  yield task3();
}

const executor = taskExecutor();
executor.next(); // Execute task1
executor.next(); // Execute task2 after task1 completes
executor.next(); // Execute task3 after task2 completes

Animation Sequences:

Generators can be used to create smooth animation sequences, allowing you to control the timing of each step.

function* animate() {
  yield moveElement("element1", { x: 100, y: 200 });
  yield moveElement("element2", { x: 50, y: 100 });
  // and so on...
}

const animation = animate();
animation.next(); // Move element1
animation.next(); // Move element2 after element1 completes