Recap for the last two months: hxbolts

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:

  1. Authorize;
  2. Get all posts ids;
  3. Get all comments ids for specific post;
  4. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.