-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Conditional/Branching construct #1454
base: master
Are you sure you want to change the base?
Conversation
As in the closed issue, usually we recommend writing a Promise.resolve(email)
.then(iff(e => e.length > 5, // Conditional
e => console.log('Valid: ', e), // ifTrue
e => console.error(e))) // ifFalse Main benefit being that this |
I support that pattern (exposed as Mainly I hate having to patch bluebird with my util/helpers. (tired of disclaiming - "don't ever normally hack onto native prototypes...") You might ask, Well then, "why?" Is this scope creep? I'd say bluebird is already a batteries-included library. Adding something that seems more relevant than |
@spion that is really close, but if I wanted to write my function chains that way I'd use https://github.com/sindresorhus/ (still awesome) 1000 mini promise libs. 😉 |
Here's the ES6 I'm working off, hopefully easier to read/review: module.exports = function _conditionals(Promise) {
Promise.prototype.thenIf = thenIf
Promise.thenIf = _thenIf
function thenIf(cond = (x) => x, ifTrue = (x) => x, ifFalse = () => null) {
if (this instanceof Promise) {
return this.then(value => _thenIf(cond, ifTrue, ifFalse)(value))
} else {
return _thenIf(cond, ifTrue, ifFalse)
}
}
function _thenIf(cond = (x) => x, ifTrue = (x) => x, ifFalse = () => null) {
return value => Promise.resolve(cond(value))
.then(ans => ans ? ifTrue(value) : ifFalse(value))
}
} |
Bluebird's external API is currently closed-by-default, unless there is a significant new construct that provides important new functionality (e.g. using, streams, etc). API that can be achieved by adding a combinator is generally not added anymore since we find that the large API surface area burden on users outweighs the gain (users look at the documentation, see the billion methods and give up immediately) This sucks, but unfortunately JS's OO flavour doesn't make it easy to separate extensions from a library, so either everyone is burdened with a large surface area, or noone gets all the features they want. Maybe the bind operator would make things better, if only TC39 got their act together in pushing it through. @benjamingr @petkaantonov correct me if I'm wrong. |
Thanks @spion - agreed, bind::can't come soon enough. I understand the criticism of bluebird is often about bloat. To me, this is because Bluebird was used primarily as a browser polyfill for years. Most people only used Bluebird is special because of it's inclusive API - it's more amazing that it's only a few dozen KB (and in the age of 3MB JS bundles... not bad).To me, the value of the inclusive API becomes clear in comparison to RxJS' patterns. ... And if I add some EventEmitter code, i'll be at 90% of RxJS. 😀 Speaking of scaring users off... Btw, the API reference page is an excellent, simple & clear landing page. |
I keep finding examples where const ensureDirectory = (file) => Promise
.resolve(path.join(__dirname, '..', file.category))
.tapIf(fs.existsAsync, fs.mkdirAsync) // <-- oh daayyyum!!!
.then(() => file)
// Will create folder path (if needed), then return the input `file` |
@spion And how on earth does my code affect this unrelated file? 😖 Thanks! |
Seems like a good way to easily add if/else conditions. 👍 |
This is a proposed change related to #984
And my comments/examples here: #984 (comment)
API
Defaults
condition
, echo/truthy function:(x) => x
ifTrue
, echo function:(x) => x
ifFalse
, quiet function:() => null
The
condition
function should return eithertrue
/false
or a promise that resolves to somethingtrue
/false
.ifTrue
function is called if thecondition
resulted in a truthy value. Conversely,ifFalse
will be called if we got a false answer.The return value of either
ifTrue
/ifFalse
handler will be handed to the next.then()
.Usage
Lots of cool stuff is possible, the default values let you call
.thenIf
with no args - if you simply want to exclude falsey values down the chain.