The Functional Promises library is a Fluent API supporting a specific Function Chaining technique (using composition).
Note:
FP
doesn't replace or extend Promises. It uses them.
There are many names for this general pattern. Including Collection Pipeline and Promise Chain. The emphasis here is a seamless async/sync Developer Experience.
I call this pattern a Functional River
- your data
is the water, and your functions
describe its path or riverbed.
- Only 400 Lines of Source & 3Kb compressed
- Easily handle Sync, Async, Events, Promises, and Callbacks.
- Familiar methods, including
Array.prototype.map
,[].filter()
,[].find()
,[].some()
, etc. - Create Monads in JavaScript (so far as they contain side-effects to a sequence of instructions).
- Point-free code is easily achieved (no temp variables).
- Higher code test coverage w/ less repetitive code in tests.
- Use the best features from multiple programming styles: a little imperative, plenty functional, a pinch of OOP, yet still resembling declarative methods!!!
Total Lines of Code (LoC) calculated using cloc
CLI utility.
LoC #'s included because a smaller surface === fewer places bugs can hide.
Library | Main deal | Files | Lines of Code | .min.js kB |
---|---|---|---|---|
Functional Promise v1.8.1 | Sync & Async Chains | 8 | 375 | 12 Kb (3Kb compressed) |
Bluebird v3.5.1 | Promises Replacement | 38 | 5,188 | 80 Kb |
RxJS v5.5.6 | Observables Chaining | 458 | 12,266 | 150 Kb |
IxJS v2.3.4 | [Async]Iterable Chaining | 521 | 12,366 | 145 Kb |
Admittedly IxJS
/RxJS
have a far larger API than FP
also some behavior in RxJS
/IxJS
may never be added.
Currently however there is a lot of overlap with FP
(plus more planned).
The table above show FP
is roughly 1/30th the LOC (lines of code) in R/IxJs
.
FP
's bundle size is about 10% the size of either RxJS
/IxJS
.
BluebirdJS
and FP
have roughly the same number of API methods, yet Bluebird
has a fair bit more code.
To be clear: Bluebird and RxJS/IxJS are amazing. Their interface/designs has been very influential on
FP
.Note: R/IxJS's hyper-modular design also allows for bundles to be lots smaller (though using quite different syntax, either
.pipe(...)
orix/iterable
/ix/add/...
).
npm install functional-promises
Use one of the following:
const FP = require('functional-promises')
// or:
import FP from 'functional-promises'
Using .map()
FP.resolve([1, 2, 3, 4, 5])
.map(x => x * 2)
.map(x => x * 2)
.then(results => {
// results === [4, 8, 12, 16, 20]
})
Handling Events
Create function chains to handle the case where promises don't fit very naturally.
For example streams & event handlers must (usually) support multiple calls over time.
Here's how FP.chain()
and FP.chainEnd()
/FP.listen(obj, event)
help you handle this like a pro:
const button = document.getElementById('submitBtn')
FP.chain() // start a chain
.then(({target}) => { // destructure 'target' from the `event`
target.textContent = 'Clicked!'
})
.listen(button, 'click') // end the repeatable chain, started at `.chain()`
git clone [email protected]:functional-promises/functional-promises.git
cd functional-promises
npm install
npm test
Thanks to several influencial projects: RxJS, IxJS, Bluebird, asynquence, FantasyLand, Gulp, HighlandJS, et al.
Special thanks to Kyle Simpson, Eric Elliot, and Sarah Drasner for their work for the OSS community, as well as their advice & encouragement.