Go

Overview

We are going to take a look at csp-coffee/go package. It provides a named export for go function which is used to run our routines aka generators. Let's recall our hello world example to explain things.

import { makeChannel } from 'csp-coffee/channel';
import { go } from 'csp-coffee/go';
import { take, putAsync } from 'csp-coffee/operators';

const ch = makeChannel();

function* helloWorldRoutine () {
    const greeting: string = yield take(ch);

    console.log(greeting);
}

const { cancellablePromise } = go(helloWorldRoutine)
cancellablePromise.then(() => {
    console.log('DONE!');
})

putAsync(ch, 'Hello World!');
// Will print "Hello Roman!"

We see that our go function can accept a generator function and return an object with some properties, in this case it we make use of cancellablePromise property. You can think of cancellablePromise as a usual promise with a little bit of magic which we will explore later. go function in responsible for running our generators.

Yielding magic

Additionally go function supports yielding promises, generators and operators inside your generator functions and will handle them correctly.

import { go } from 'csp-coffee/go';

function delay(ms: number) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms);
    })
}

function* justAnotherGenerator (name: string) {
    yield delay(1000);
    console.log('HI ' + name);
}

function* yieldingMagicGenerator () {
    yield justAnotherGenerator('Roman');
}

go(yieldingMagicGenerator) // will log 'HI Roman' after ~1000msja

Passing paratemers to our routine

Any additional parameters supplied to go function will be passed to a provided generator function as arguments. We can alter our example a bit to demonstrate this concept.

import { makeChannel } from 'csp-coffee/channel';
import { go } from 'csp-coffee/go';
import { take, putAsync } from 'csp-coffee/operators';

const ch = makeChannel();

function* helloWorldRoutine (name: string) {
    const greeting: string = yield take(ch);

    console.log(`${greeting} ${name}!`);
}

const { cancellablePromise } = go(helloWorldRoutine, 'Roman')
cancellablePromise.then(() => {
    console.log('DONE!');
})

putAsync(ch, 'Hello');

// Will print "Hello Roman!"

Channel from routine

go function will also produce a channel along with cancellablePromise upon creation which will contain a value returned by generator function. This channel will be automatically closed once a value is taken. More about channels on the Channels page.

import { makeChannel } from 'csp-coffee/channel';
import { go } from 'csp-coffee/go';
import { take, putAsync, takeAsync } from 'csp-coffee/operators';

const ch = makeChannel();

function* helloWorldRoutine (name: string) {
    const greeting: string = yield take(ch);

    return `${greeting} ${name}!`;
}

const { cancellablePromise, channel } = go(helloWorldRoutine, 'Roman')
cancellablePromise.then(() => {
    console.log('DONE!');
})

putAsync(ch, 'Hello');
takeAsync(channel)
    .then((value) => {
        console.log(value) // "Hello Roman!"
    })

Last updated