Async Execution Queue in TypeScript

I’m in the process of creating a fully client-side (with server side sync) JavaScript application.
Once thing I needed was the ability to queue and execute commands asynchronously but serially.
With JQuery Promises, this is remarkably easy to achieve.

The Gist below is in typescript.

export class AsyncExecutionQueue{
private tail: JQueryPromise = $.Deferred().resolve();
public enqueue(cmd:()=>any): JQueryPromise {
console.log("Queuing Command");
var next = $.Deferred();
var client = $.Deferred();
this.tail.always(() => {
try {
var result = cmd();
if (result.done && result.fail) {
result
.done(client.resolve, next.resolve)
.fail(client.reject, next.resolve);
}
else {
client.resolve(result);
next.resolve();
}
}
catch (e) {
client.reject(e);
next.resolve();
}
});
this.tail = next;
return client;
}
}
view raw AsyncExecutionQueue hosted with ❤ by GitHub
/// <reference path="jquery-1.8.d.ts" />
/// <chutzpah_reference path="libs.bundle.js" />
/// <reference path="qunit.d.ts" />
/// <chutzpah_reference path="TestLibs.Bundle.js" />
module Tests {
declare var JsMockito: any;
declare var JsHamcrest: any;
JsHamcrest.Integration.QUnit();
JsMockito.Integration.QUnit();
var queue: AsyncExecutionQueue;
QUnit.module("Async Execution Queue", {
setup: () =>{
queue = new AsyncExecutionQueue();
}
});
QUnit.asyncTest("should pass back errors from commandhandlers", () => {
var cmd = () => {
throw new Error("Exception");
};
queue.enqueue(cmd)
.always(start)
.done(() => ok(false, "Error was not returned"))
.fail((error) => ok(true, "Error was returned"));
});
QUnit.asyncTest("should execute next command if current command failed", () => {
var cmd1 = () => {
throw new Error("Exception");
};
var cmd2 = () => {
return "success";
};
queue.enqueue(cmd1);
queue.enqueue(cmd2)
.always(start)
.done((result) => QUnit.equal("success", result, "Second command execeuted"))
.fail((error) => ok(false, "Error was returned"));
});
QUnit.asyncTest("should execute commands serially", () => {
var results = [];
var cmd = (n) => {
var wait = Math.floor((Math.random() * 50) + 1);
return $.Deferred((d) => setTimeout(() => {
console.log("Executing Handler " + n + " took " + wait)
results.push(n);
d.resolve();
}, wait));
};
var result = $.when(
queue.enqueue(() => cmd(1)).done(() => console.log("Done with 1")),
queue.enqueue(() => cmd(2)).done(() => console.log("Done with 2")),
queue.enqueue(() => cmd(3)).done(() => console.log("Done with 3")),
queue.enqueue(() => cmd(4)).done(() => console.log("Done with 4")),
queue.enqueue(() => cmd(5)).done(() => console.log("Done with 5")),
queue.enqueue(() => cmd(6)).done(() => console.log("Done with 6")),
queue.enqueue(() => cmd(7)).done(() => console.log("Done with 7"))
);
result
.always(start)
.done(() => QUnit.deepEqual(<any>[1, 2, 3, 4, 5, 6, 7], <any>results, "Commands Executed Out of Order"))
.fail((e) => ok(false, e))
});
}
Tagged , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: