At work and for my own projects I tried to use different promise libraries, for javascript, for java (mostly on android) and of course for haxe. And I absolutely love Bolts library from corporationname (ooops, actually I can’t write it because of BSD license). Anyway, it is good strongly typed (using generics) promise library for java.
Introducing hxbolts! A pure-haxe and cross-platform port of “tasks” component from Bolts.
Imagine you have to delete all comments from blog while player playing in your game, mwahahaha 😈 . But server API has only 4 methods:
- Authorize;
- Get all posts ids;
- Get all comments ids for specific post;
- Delete specific comment by id.
Let you have a function for making async requests:
private static function makeRequestAsync(
url : String,
callback : String -> Void
) : Void { ... }
Usually code will look like
var token : String = null;
makeRequestAsync("http://blog.tld/api/authorize?user=me", function(result : String) : Void {
try {
token = Reflect.field(Json.parse(result), "token");
} catch (e : Dynamic) {
trace("Error occurred : " + Std.string(e));
return;
}
makeRequestAsync('http://blog.tld/api/postsIds?token=${token}', function(result : String) : Void {
var ids : Array<Int>;
try {
ids = cast Json.parse(result);
} catch (e : Dynamic) {
trace("Error occurred : " + Std.string(e));
return;
}
var results = new Array<String>();
for (id in ids) {
makeRequestAsync('http://blog.tld/api/commentsIds?token=${token}&postId=${id}', function(result : String) : Void {
results.push(result);
if (results.length == ids.length) {
// ...
}
});
}
});
});
Uh oh… And I don’t even started deletion process.
hxbolts coming to the rescue!
At first we need to boltify makeRequestAsync function:
private static function makeRequestTask(url : String) : Task<String> {
var tcs = new TaskCompletionSource<String>();
makeRequestAsync(url, function(result : String) : Void {
tcs.setResult(result);
});
return tcs.task;
}
The rest is easy:
var token : String = null;
makeRequestTask("http://blog.tld/api/authorize?user=me").onSuccessTask(function(task : Task<String>) : Task<String> {
token = Reflect.field(Json.parse(task.result), "token");
return makeRequestTask('http://blog.tld/api/postsIds?token=${token}');
}).onSuccessTask(function(task : Task<String>) : Task<Array<String>> {
var tasks = new Array<Task<String>>();
for (id in (cast Json.parse(task.result) : Array<Int>)) {
tasks.push(makeRequestTask('http://blog.tld/api/commentsIds?token=${token}&postId=${id}'));
}
return Task.whenAllResult(tasks);
}).onSuccessTask(function(task : Task<Array<String>>) : Task<Void> {
var tasks = new Array<Task<String>>();
for (response in task.result) {
for (id in (cast Json.parse(response) : Array<Int>)) {
tasks.push(makeRequestTask('http://blog.tld/api/deleteComment?token=${token}&commentId=${id}'));
}
}
return Task.whenAll(tasks);
}).continueWith(function(task : Task<Void>) : Void {
if (task.isSuccessed) {
trace("Everything is good");
} else {
trace("Error occurred : " + Std.string(task.error));
}
});
Code is linear, easy to understand. It even doesn’t contains try / catch blocks, because hxbolts will take care about exceptions.
More examples at readme file in hxbolts repo.
