Last active
August 29, 2015 13:58
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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" | |
} ); |
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
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.