Skip to content

Instantly share code, notes, and snippets.

@getify
Last active August 29, 2015 13:58
Show Gist options
  • Save getify/10172207 to your computer and use it in GitHub Desktop.
Save getify/10172207 to your computer and use it in GitHub Desktop.
using asynquence's `runner(..)` plugin to do async CSP-style (message-passing) generator co-routines
// just a silly number generator that's promise-async
function getVal() {
return new Promise( function(resolve,reject){
setTimeout( function(){
if (!getVal.__number) getVal.__number = 0;
resolve( getVal.__number += 10 );
}, 100 );
} );
}
// **********************
ASQ( 2, 3 )
.runner(
// machine 1
function*(token){
token.messages; // [2, 3]
token.messages[0] += yield getVal(); // pauses generator while promise resolves
token.messages[1] += yield getVal(); // pauses generator while promise resolves
token.messages.push( token.messages[0] + token.messages[1] );
token.messages; // [12, 23, 35]
yield token; // hand control over to next machine
token.messages; // [ 100 ]
token.messages[0] += yield getVal(); // pauses generator while promise resolves
// implicit finish means transfer control to next machine
},
// machine 2
function*(token){
token.messages; // [12, 23, 35]
token.messages = [ token.messages[0] + token.messages[1] + token.messages[2] ];
token.messages; // [ 70 ]
token.messages[0] += yield getVal(); // pauses generator while promise resolves
token.messages; // [ 100 ]
yield token; // hand control over to next machine
token.messages; // [ 140 ]
token.messages.push( "Hello World" );
yield token.messages;
}
)
.val( function(msgs){
console.log( msgs[0], msgs[1] ); // 140 "Hello World"
} );
@Taytay
Copy link

Taytay commented Jun 23, 2014

This is awesome. I would love to see a direct translation into non ES6 code. I get the "substitute yield token" for "return token", but don't quite have my head wrapped around how I would structure machine1 and machine2 as sequences instead of ES6 generators.

@Taytay
Copy link

Taytay commented Jun 23, 2014

Actually, I got it working after all. I don't know if this is an idiomatic translation, but it gets the job done.
This is written in typescript, so there is some extra type fluff that you can (hopefully) ignore.

I was particularly curious what the best way was to translate token.messages[0] += yield getVal();
I ended up with:

            .then((theToken:any)=> {
                token = theToken;
                return getVal();
            })
            .then((value:any)=>{
                token.messages[0]+= value;
...

Not sure if that's the cleanest or best way to do this.

Here's the full code:

it("Can pass messages back and forth between two routines, just like another gist", function (testDone) {
    //just a silly number generator that's promise-async
    function getVal() {
        return new Promise( function(resolve,reject){
            setTimeout( function(){
                if (!(<any>getVal).__number) (<any>getVal).__number = 0;
                resolve( (<any>getVal).__number += 10 );
            }, 100 );
        } );
    }


    var machine1 = function(){
        var token : any = null;
        return ASQ.iterable()
            .then((theToken:any)=> {
                token = theToken;
                return getVal();
            })
            .then((value:any)=>{
                token.messages[0]+= value;
                return getVal();
            })
            .then((value:any)=>{
                token.messages[1]+= value;
                token.messages.push( token.messages[0] + token.messages[1] );
                return token;
            })
            .then(()=>{
                return getVal();
            })
            .then((value:number)=>{
                token.messages[0] += value;
            })
    }

    var machine2 = function(){
        var token : any = null;
        return ASQ.iterable()
            .then((theToken:any)=> {
                token = theToken;
                token.messages = [ token.messages[0] + token.messages[1] + token.messages[2] ];
                return getVal();
            })
            .then((value:any)=>{
                token.messages[0] += value;
                return token;
            })
            .then(()=>{
                token.messages.push( "Hello World" );
                return token.messages;
            })

    }


    ASQ( 2, 3 )
        .runner(
        machine1(),
        machine2()
    )
        .val( function(msgs){
            console.log( msgs[0], msgs[1] ); // 140 "Hello World"
            expect(msgs[0]).to.equal(140);
            expect(msgs[1]).to.equal("Hello World");
            testDone();
        } )
        .catch((e:Error)=>{
            testDone(e)}
    );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment