Coder Social home page Coder Social logo

ajeeb-coroutines's Introduction

Ajeeb Coroutines

Unity-inspired Coroutines for the browser and nodejs.

Ajeeb Coroutines are a TypeScript implementation of a similar idea from the Unity 3D engine. They use ES6 generators to turn code that reads synchronously into code that runs across multiple frames. They were designed for the Ajeeb Game Engine but have no dependencies and can be used anywhere.

Installation

npm install nasser/ajeeb-coroutines

Or in a browser you can link to the CDN, using either legacy script tags

<script src="https://cdn.jsdelivr.net/gh/nasser/ajeeb-coroutines@master/build/coroutines.iife.js"></script>

or ES6 modules

<script type="module">
import * as coro from "https://cdn.jsdelivr.net/gh/nasser/ajeeb-coroutines@master/build/coroutines.esm.js"
</script>

Usage

An instance of an ES6 generator is treated as a coroutine. An instance of the [[Schedule]] class schedules and runs coroutines.

[[Schedule.add]] adds a couroutine to the collection. [[Schedule.tick]] runs every coroutine in the collection up to their next yield statement. Each coroutine remembers the last yield they reached, and the next time [[Schedule.tick]] is called they resume execution from that point.

import { Schedule } from "ajeeb-coroutines"

let sched = new Schedule()

sched.add(function* () {
    console.log("hello")    // prints "hello"
    yield;                  // waits until next tick
    console.log("world")  
    console.log("how")      // prints "world" and "how"
    yield; yield;           // waits for two ticks
    console.log("are you?") // prints "are you?"
})

sched.tick()
// prints "hello"
sched.tick()
// prints "world"
// prints "how"
sched.tick()
// does nothing
sched.tick()
// prints "are you?"
// further calls to sched.tick() will do nothing

Coroutines are designed to run across multiple frames. [[tick]] can be scheduled to run regularly setInterval or requestAnimationFrame in a browser. This advances every coroutine in the collection automatically once per frame. When scheduled like this, you can think of yield as a way of "waiting one frame".

import { Schedule } from "ajeeb-coroutines"

let sched = new Schedule()

sched.add(function* () {
    console.log("hello")    // prints "hello" and waits one frame
    yield;
    console.log("world")    // prints "world" and waits two frames
    yield; yield;
    console.log("how")      // prints "how" and waits three frames
    yield; yield; yield;
    console.log("are")      // prints "are" and waits four frames
    yield; yield; yield; yield;
    console.log("you?")     // prints "you?"
})

setInterval(() => sched.tick(), 1000 / 60) // tick 60 times a second

Generators are normal JavaScript functions. They have access to local variables, closures, arguments, and more. yield can appear anywhere.

import { Schedule } from "ajeeb-coroutines"

let sched = new Schedule()

function* hello(repeat) {
    console.log("hello")    // prints "hello" and waits one frame
    yield;
    for(let i=0; i<repeat; i++) { 
        console.log("world")    // prints "world" and wait one frame
        yield;                  // execution will resume from this point 
    }
    console.log("!")     // prints "!"
}

sched.add(hello)

setInterval(() => sched.tick(), 1000 / 60) // tick 60 times a second

This library also exports a number of generically useful coroutines, like [[wait]], that can be combined with your own in powerful ways. A coroutine can be made to wait for another coroutine with the yield* statement. If yield is read as "wait one frame" yield* is read as "wait until this other coroutine completes"

import { Schedule, wait } from "ajeeb-coroutines"

let sched = new Schedule()

// schedule coroutines to tick every frame
// in the browser
function runCoroutines() {
    requestAnimationFrame( runCoroutines )
    sched.tick()
}
runCoroutines()

// in node
setInterval(() => sched.tick(), 1000/60)

// you can add coroutines afterwards
sched.add(function* () {
    console.log("hello")  // prints "hello"
    yield* wait(2)        // wait for 2 seconds
    console.log("world")  // prints "world"
    yield* wait(3)        // waits 3 seconds
    console.log("!!!")    // prints "!!!"
})

// prints "hello" immediately 
// waits 2 seconds
// prints "world" 
// waits 3 seconds
// prints "!!!" 

Coroutines can be treated as normal functions. They take arguments, and can be as complex as needed.

import fs from "fs"
import { Schedule, waitUntil } from "ajeeb-coroutines"

let sched = new Schedule()

function* waitForFile(path) {
    console.log("waiting for", path);
    yield* waitUntil(() => fs.existsSync(path))
    console.log("ok");
}

sched.add(waitForFile("nice.txt"))

// in the browser
function runCoroutines() {
    requestAnimationFrame( runCoroutines )
    sched.tick()
}
runCoroutines()

// in node
setInterval(() => sched.tick(), 1000/60)

ajeeb-coroutines's People

Contributors

dependabot[bot] avatar nasser avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.