I am parsing data like this:
getData()
.filter(fn)
.filter(fn2)
.filter(fn3)
.map(fn4)
in which the filters are conceptually separated and do different operations.
For debugging purposes, is there a JavaScript library or a way to wrap promises such that I can do this:
getData()
.filter(fn)
.then((result) => { log(result.count); return result })
.filter(fn2)
.then(debugFn) // extra chained debug step (not iterating through arr)
.filter(fn3)
.map(fn4)
Or is this an anti-pattern?
EDIT
After some thoughts I'm convinced that the best answer to this question has been given by V-for-Vaggelis: just use breakpoints.
If you do proper function composition then inserting a few tap
calls in your pipeline is cheap, easy and non intrusive but it won't give you as much information than what a breakpoint (and knowing how to use a debugger to step through your code) would.
Applying a function on x
and returning x
as is, no matter what, already has a name: tap
. In libraries like ramda.js, it is described as follow:
Runs the given function with the supplied object, then returns the object.
Since filter
, map
, ... all return new instances, you probably have no other choice than extending the prototype.
We can find ways to do it in a controlled manner though. This is what I'd suggest:
const debug = (xs) => {
Array.prototype.tap = function (fn) {
fn(this);
return this;
};
Array.prototype.debugEnd = function () {
delete Array.prototype.tap;
delete Array.prototype.debugEnd;
return this;
};
return xs;
};
const a = [1, 2, 3];
const b =
debug(a)
.tap(x => console.log('Step 1', x))
.filter(x => x % 2 === 0)
.tap(x => console.log('Step 2', x))
.map(x => x * 10)
.tap(x => console.log('Step 3', x))
.debugEnd();
console.log(b);
try {
b.tap(x => console.log('WAT?!'));
} catch (e) {
console.log('Array prototype is "clean"');
}
If you can afford a library like Ramda, the safest way (IMHO) would be to introduce tap
in your pipeline.
const a = [1, 2, 3];
const transform =
pipe(
tap(x => console.log('Step 1', x))
, filter(x => x % 2 === 0)
, tap(x => console.log('Step 2', x))
, map(x => x * 10)
, tap(x => console.log('Step 2', x))
);
console.log(transform(a));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {pipe, filter, map, tap} = R;</script>