Closed tgvashworth closed 9 years ago
An example, in slightly verbose JS...
class Some {
constructor(v) {
this.value = v;
}
then(f) {
return f(this.value);
}
}
class None {
then() {
return this;
}
}
const Maybe = {
Some: x => new Some(x),
None: new None()
};
// Compose two functions that both take a request, but only *might* pass
// the request on.
// compose :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
const Thenable = {
compose: (f, g) => x => g(x).then(f),
composeMany: (...fs) =>
fs.reverse().reduce((g, f) => Thenable.compose(f, g))
};
const filterRequest = r => (
r.path.startsWith('/boop')
? Maybe.Some(r)
: Maybe.None
);
const isInFlight = r => false; // TODO!
const dedupeRequest = r => (
isInFlight(r)
? Maybe.None
: Maybe.Some(r)
);
const addAuthHeaders = r => (
r.headers = { Authorization: 'yes, please' },
r
);
const boopDedupe = Thenable.composeMany(addAuthHeaders, dedupeRequest, filterRequest);
Head over here to see it in action.
While this is conceptually compatible with Promises, it might as well just be Promises. Will work on a sketch.
Closing, as this is now better addressed in #1.
Issue #1 threw up a question about combining plugins, or only applying them to a subset of requests. It's desirable that an existing composition can be further composed.
Each plugin needs to be able to 'drop' the request, and prevent it from going any further. This lends itself well to the 'then' pattern that JSers have learnt from Promises. Example to follow...