Composing steps
by andrewdavey
HTML
<ul id="log">
</ul>
JavaScript
function define(type, fn) {
return function() {
var args = Array.prototype.slice.apply(arguments);
return new type(fn, args);
}
};
function Step(func, args) {
this.func = func;
this.args = args;
}
Step.prototype.run = function(context, done, fail) {
try {
this.func.apply(context, this.args);
done();
} catch (e) {
fail(e);
}
};
function AsyncStep(func, args) {
this.func = func;
this.args = args;
}
AsyncStep.prototype.run = function(context, done, fail) {
try {
context.done = done;
context.fail = fail;
this.func.apply(context, this.args);
} catch (e) {
fail(e);
}
};
function Assertion(func, args) {
this.func = func;
this.args = args;
}
Assertion.prototype.run = function(context, done, fail) {
try {
var result = this.func.apply(context, this.args);
if (result) {
done(result);
} else {
fail(result);
}
} catch (e) {
fail(e);
}
};
var say = define(Step, function(msg) { log(msg); });
var wait = define(AsyncStep, function(ms) {
setTimeout(this.done, ms);
});
var answer = 42;
var answerIs = define(Assertion, function(number) { return answer === number; });
var steps = sequence([
say("hello"),
wait(500),
say("world")
]);
var assertions = tryAll([
answerIs(42),
answerIs(42)
]);
sequence([steps, wait(500), assertions])
.run(
{},
function(result) {
log(JSON.stringify(result));
},
function(results) {
log("Some failed: " + JSON.stringify(results));
}
);
function sequence(actions) {
return {
run: function(context, done, fail) {
actions.reduceRight(
function(next, action) {
return function() {
action.run(context, next, fail);
}
},
done
)();
}
...