Lua-like pseudo-coroutine that wraps iterators.
npm install luacoro[![Build Status][travisci-image]][travisci-url]
[![npm][npm-image]][npm-url]
[![Dependency Status][dependencies-image]][dependencies-url]
[![MIT License][license-image]][license-url]
[npm-image]: https://badge.fury.io/js/luacoro.svg
[npm-url]: https://badge.fury.io/js/luacoro
[travisci-image]: https://travis-ci.org/townewgokgok/luacoro-js.svg?branch=master
[travisci-url]: https://travis-ci.org/townewgokgok/luacoro-js
[dependencies-image]: https://david-dm.org/townewgokgok/luacoro-js.svg
[dependencies-url]: https://david-dm.org/townewgokgok/luacoro-js
[license-image]: https://img.shields.io/badge/License-MIT-blue.svg
[license-url]: https://opensource.org/licenses/MIT
Lua-like pseudo-coroutine for JavaScript/TypeScript using generator.
Demo
TOC
- Installation
- Examples
- Error handling
- Golang-like defer
- Functions
- Function create
- Function concurrent
- Function all
- Function race
- Function forever
- Function defer
- Class Coroutine
- Method resume
- Method stop
- Accessor isAlive
- Class ComposedCoroutine
- Method add
``bash`
npm install --save luacoro
`typescript`
import * as luacoro from 'luacoro'
// or
const luacoro = require('luacoro')
Example code is also displayed in the demo.
Can handle errors just like normal functions.
`typescript
it('handles error', () => {
let result = ''
function* second (): luacoro.Iterator<{}> {
throw new Error('an error')
}
function* first (): luacoro.Iterator<{}> {
try {
yield second()
} catch (e) {
result += 'caught '
}
yield second()
}
const c = luacoro.create(first())
try {
c.resume()
} catch (e) {
result += e.message
}
expect(result).toEqual('caught an error')
})
`
luacoro.defer works like Golang's defer.
Useful to clean up scene scoped resources.
Defer functions must be normal functions.
Not yieldable within them.
See examples/browser/src/guide.ts for example.
`typescript${lastCursorPos.x}px
function addClickEffect () {
coro.add(function* (): luacoro.Iterator<{}> {
const e = document.createElement('div')
e.classList.add('guide-click-effect')
document.getElementById('guide').appendChild(e)
luacoro.defer(() => {
e.remove()
})
e.style.left = ${lastCursorPos.y}px
e.style.top =
for (let i = 1; i <= clickEffectFrames; i++) {
const s = easingOut(i / clickEffectFrames)
e.style.transform = translate(-50%, -50%) scale(${s}, ${s})${1 - s}
e.style.opacity = `
yield
}
})
}
`typescript`
create
Create a new coroutine to iterate start first.start normally must be an iterator generated by a generatoryield
implemented to (or return) values of the following 3 types:
- o: An instance of arbitary class or plain object | string | Arrayresume()
- returns o.o
- If has a wait field, resume() returns nullo.wait - 1
through frames after that.n
The iterator is not resumed while this, which means that
this coroutine waits frames including the current frame.
- n: A numberresume()
- returns null.resume()
- After that, returns null through n - 1 frames.n
The iterator is not resumed while this, which means that
this coroutine waits frames including the current frame.
- i: An Iterator of the same type as starti
- When is returned, the current iterator is terminatedi
and is immediately started to iterate as the replacement.i
- When is yielded, the current iterator is paused and pushed onto the stack,i
and is immediately started to iterate.i
After is terminated, the caller iterator is popped from the stacki
and continued to be iterated.
At this time, the return value of can be got.
`typescript`
concurrent
Create a new coroutine to iterate all coroutines concurrently.
This coroutine will never die.
Additional coroutines can be added by add.
Dead coroutines will be removed automatically.
`typescript`
all
Create a new coroutine to iterate all coroutines
concurrently until the all of them are dead.
Dead coroutines will not be removed to keep array indexes of the yielded value.add
Adding coroutines by is discouraged.
`typescript`
race
Create a new coroutine to iterate all coroutines
concurrently until one of them is dead.
Array indexes of the yielded value will be keeped.add
Adding coroutines by is discouraged.
`typescript`
forever
Create a new coroutine that repeats
generating iterator and iterating it forever.
`typescript`
defer (fn: () => void)
Register fn to be invoked when exiting the caller iterator.
Works like Golang's defer.
`typescript`
resume(resumeValue?: T): T
Resume the current iterator and receive the yielded value at the next frame.
This method will return nulls forever after the coroutine stops.
`typescript`
stop(): void
Stop this coroutine.
`typescript`
get isAlive(): boolean
Whether this coroutine is alive.
Coroutine that wraps multiple iterators and yields results in an array.
`typescript`
add (coroutine: Coroutinizable
Add a coroutine` to iterate together.