-
Notifications
You must be signed in to change notification settings - Fork 1
Guide
Firstly, if you haven't read the Tutorial, now is the time.
In this guide, you will learn about some important things when using asyncflow.
In short, put your callback as the last argument of the function. Like:
function myAsyncFunc(arg1, arg2, callback) {
...
}
If your functions are not written in this convention, you will have to write wrappers for them manually, like:
function strangeFunc(callback, arg) {
...
}
function shinyStrangeFunc(arg, callback) {
strangeFunc(callback, arg);
}
Now, the whole reason you wrap a function with flow.wrap
is so you can call it in a synchronous way within a flow block. So would you want to wrap a synchronous function?
DON'T DO THIS:
var flow = require("asyncflow");
function sum(a, b) {
return a + b;
}
var sum$ = flow.wrap(sum);
flow(function() {
var result = sum$(1, 2).wait();
...
});
Instead, you just do this:
var flow = require("asyncflow");
function sum(a, b) {
return a + b;
}
flow(function() {
var result = sum(1, 2);
...
});
It is really bad for health to wrap a synchronous function, you've been warned!!! That way said, if you really want to convert a synchronous function into a asynchronous one, you can do it with a call to process.nextTick
.
function sum(a, b, callback) {
process.nextTick(function() {
callback(a + b);
});
}
Bear in mind that a flow block is just a asyncflow call.
var flow = require("asyncflow");
// This flow block is just an asynchronous call like any others.
flow(function() {
...
});
Flow block cannot track an non-wrapped asynchronous call, so you won't be able to achieve the synchronous style desired in a flow block. In short, don't do it.
DON'T DO THIS:
var flow = require("asyncflow");
var fs = require("fs");
var readFile = flow.wrap(fs.readFile);
flow(function() {
fs.exists("file.txt", function(exists) {
if (exists) {
var data = readFile("file.txt").wait();
...
}
});
});
Instead, do this:
var flow = require("asyncflow");
var fs = require("fs");
var exists = flow.wrap(fs.exists);
var readFile = flow.wrap(fs.readFile);
flow(function() {
if (exists("file.txt").wait()) {
var data = readFile("file.txt").wait();
...
}
});
I mean, it's meaningless, plus it causes exceptions to throw (obviously).
While this is not specific to asyncflow, but to all of Node.js, I feel I have to mention it here.
Exceptions thrown in an asynchronous call are not able to be caught, so they should be avoided. e.g.
function errorFunction(cb) {
setTimeout(function() {
throw new Error("custom error");
cb(null);
}, 10);
}
The exception thrown in the code above cannot be caught by a try catch block. The best you can do, is to rewrite it like this:
function errorFunction(cb) {
setTimeout(function() {
try {
throw new Error("custom error");
cb(null);
} catch (e) {
cb(e);
}
}, 10);
}
Consider:
var mapped = [1, 2, 3].map(function(v) {
return v * 2;
});
If you want to use the parallel version of map, you will have to write this:
var flow = require("asyncflow");
flow(function() {
var mapped = flow.wrapped.map([1, 2, 3], flow.wrap(function(v, i, a, cb) {
process.nextTick(function() {
cb(v * 2);
});
})).wait();
});
Notice that we had to convert the mapping function into an asynchronous version, and, we also had to specify the complete argument list for the mapping function. This is because the callback we added has to be the last argument and the mapping function is actually be called with these 3 arguments already.
Another way to avoid specifying the whole argument list is to use function's arguments
manipulation:
var flow = require("asyncflow");
flow(function() {
var mapped = flow.wrapped.map([1, 2, 3], flow.wrap(function(v) {
var cb = arguments[arguments.length - 1];
process.nextTick(function() {
cb(v * 2);
});
})).wait();
});