Coroutine
Coroutines are implemented using generator functions. A generator
function allows you to pause the execution of a function at any point
and later resume it from where it left off. This is done using the
yield keyword.
function* myGenerator() {
console.log("Start")
yield // Pause till next() is called
console.log("Resumed")
yield // Pause again
console.log("End")
}
const co = myGenerator()
co.next() // Start
co.next() // Resumed
co.next() // End
receive values from generator functions
function* myGenerator() {
yield 1
yield 2
yield 3
}
const co = myGenerator()
console.log(co.next())
console.log(co.next())
console.log(co.next())
console.log(co.next())
Expected output:
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
send values to generator functions
function* myGenerator() {
console.log(yield 1)
console.log(yield 2)
}
const co = myGenerator()
const val1 = co.next().value
const val2 = co.next(val1 * 2).value
co.next(val2 * 2)
Expected output:
2
4
what about yielding functions
function* myGenerator() {
yield (cb) => setTimeout(cb, 1000)
console.log('done')
}
const co = myGenerator()
const fn = co.next().value
fn(() => co.next())
We just eliminated callback hell!
make it more useful
A simple coroutine runner:
function run(generator) {
const co = generator()
function next(value) {
const { value: fn, done } = co.next(value)
done || fn((err, result) => next([err, result]))
}
next()
}
We can use it like this:
const delay = time => cb =>
setTimeout(cb, time)
const asyncDouble = value => cb =>
setTimeout(() => cb(null, value * 2), 1000)
function* myGenerator() {
yield delay(1000)
console.log('1 seconds passed')
const [_, value] = yield asyncDouble(2)
console.log(value)
}
run(myGenerator)
you can do more
What about yielding multiple functions?
What about yielding a nother generator?
What about yielding promises?
That is just async/await:
async function fetchData() {
const response = await fetch('https://pokeapi.co/api/v2/pokemon/ditto')
const data = await response.json()
console.log(data)
}