15Mar/130
A Loop for WinJS Promises
I had a co-worker ping me from an internal mailing list recently because he was having trouble reading from a network stream. I dug this out of mothballs from Win8 Consumer Preview:
WinJS.Class.define('Game', function() { /* constructor */ }, { /* instance prototype */ }, { /* static members */ LoopWhileTrue: function (context, testCallback, actionReturningPromise, state) { /// <summary>Loops an action (that returns a promise) until another callback (that returns a Boolean) indicates that it should no longer continue.</summary> return new WinJS.Promise(function (success, error) { function evalActContinueLoop() { if (testCallback.call(context, state)) { var innerPromise = actionReturningPromise.call(context, state); innerPromise.then(evalActContinueLoop, function (e) { error(e); }); } else { success(state); } } evalActContinueLoop(); }); } });
This code was used for managing game state in a card-playing game app that I never finished. Usage might look like this:
var gameplay = Game.LoopWhileTrue(game, game.isGameInPlay, game.playHand, game.state);
‘gameplay’ then became a Promise that:
- is fulfilled when the entire game completes (all hands have been played or a terminal score is achieved, based on the value returned by calling game.isGameInPlay(state)).
- results in an error-fulfillment state if an internal call results in an error.
- iteratively calls game.playHand(game.state), passing in ‘game’ as the this pointer (important in JS) until it is fulfilled (see 1st bullet).
- if game.playHand completes synchronously, this method could cause a stack overflow. This can be broken with periodic use of setImmediate.
This method can conveniently be used to emulate a for-loop or a while-loop. It doesn’t quite as well emulate a do-while-loop because it checks the terminal condition, but you could write a simple adapter method to always return true for the first call to the method.
Leave a comment