Fluent asynchronous API 2: building an API
In the first post of this series, I established my requirements for a fluent asynchronous API, and showed what using such an API looks like. In this post, I’ll show what the code for the API itself looks like. On this side of things, the requirements are that writing synchronous methods in such an asynchronous API should look as close as possible to writing the same methods in a synchronous API.
Here is what the implementation of the “write” method of our “dump” sample API looks like:
this.writeSync = this.asyncify(function(text) {
Console.log(text);
return this;
});
The only difference with what I would have ordinarily written is that the method’s function definition is wrapped into a call for this.asyncify. That seems acceptable.
Asynchronous methods also have to be wrapped, so my little helper can take care of injecting the callback parameter, and the API user doesn’t have to:
this.fromFile = this.async(function(path, next) {
fs.readFile(path, function (err, text) {
if (err) throw err;
Console.log(text);
next();
});
return this;
});
For all this to work, the class needs to be instrumented from the constructor:
flasync(this);
This mixes in the “asyncify”, “async”, and “then” methods, as well as a couple private members that are needed to do the asynchronous housekeeping. “Flasync” is just the silly name for my helper library.
Here’s the full code for the “dump” API:
'use strict';
var flasync = require('../lib/flasync');
var fs = require('fs');
var Dump = function Dump() {
flasync(this);
this.write = this.asyncify(function(text) {
Console.log(text);
return this;
});
this.fromFile = this.async(function(path, next) {
fs.readFile(path, function (err, text) {
if (err) throw err;
Console.log(text);
next();
});
return this;
});
};
And that’s it for this post. Next time, I’ll dive into the madness that is the implementation of the “flasync” helper, and I'll make a confession.