@fakenickels/let-anything
Advanced tools
Comparing version 0.0.2 to 0.1.0
{ | ||
"name": "@fakenickels/let-anything", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"main": "src/index.js", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -73,2 +73,43 @@ <p align="center"> | ||
<details> | ||
<summary>Railway programming with `fp-ts` and promises</summary> | ||
[Run in CodeSandbox](https://codesandbox.io/s/exciting-cloud-d4141?file=/src/index.ts) | ||
```js | ||
import {either, function} from 'fp-ts' | ||
import {flow} from 'fp-ts/function' | ||
import {letAnything} from '@fakenickels/let-anything' | ||
// You could say I'm not a very good with TS types, I'm more of a ReasonML guy so help would be appreciated! | ||
// Here we'll provide the context to combine both Either and Promises together | ||
const letEither = letAnything<either.Either<any, any>>({ | ||
let_: (value, continuation) => { | ||
return value.then(eitherValue => { | ||
return flow( | ||
either.map(continuation), | ||
either.getOrElse(error => Promise.resolve(either.left(error))), | ||
)(eitherValue) | ||
}) | ||
} | ||
}); | ||
function* stuff() { | ||
const value = yield Promise.resolve(either.right("d")); | ||
const anotherValue = yield Promise.resolve(either.right("e")); | ||
const anotherAnother = yield Promise.resolve(either.right("bug")); | ||
return Promise.resolve(either.right(value + anotherValue + anotherAnother)); | ||
} | ||
letEither(stuff) | ||
.then(either.getOrElse(error => `Something went wrong: ${error}`)) | ||
.then(finalValue => { | ||
document.getElementById("app").innerHTML = finalValue | ||
}) | ||
``` | ||
</details> | ||
# Why? | ||
@@ -147,3 +188,5 @@ | ||
```js | ||
import {ok, error} from '' | ||
import {either} from 'fp-ts' | ||
// now this will have the type Promise<Either<any, any>> and we are not bound by the weird laws of Promise's .catch! | ||
async function findOne(id) { | ||
@@ -153,9 +196,59 @@ try { | ||
return ok(value) | ||
return either.right(value) | ||
} catch(e) { | ||
return error({error: e}) | ||
return either.left({type: 'product/findOneErr', error: e.message}) | ||
} | ||
} | ||
// ... Charge.create will be changed to the same thing and for all the other repos ... | ||
``` | ||
Now we can create a monadic context with `let-anything` and behold the power of FP with async/await easy to understand syntax! | ||
```js | ||
import {either, pipe} from 'fp-ts' | ||
import {letAnything} from '@fakenickels/let-anything' | ||
// You could say I'm not a very good with TS types, I'm more of a ReasonML guy so help would be appreciated! | ||
// Here we'll provide the context to combine both Either and Promises together | ||
const letAsyncEither = letAnything<either.Either<any, any>>({ | ||
let_: (value, continuation) => { | ||
return value.then(eitherValue => { | ||
return flow( | ||
either.map(continuation), | ||
either.getOrElse(error => Promise.resolve(either.left(error))), | ||
)(eitherValue) | ||
}) | ||
} | ||
}); | ||
function* checkoutPurchase({productId, userId}) { | ||
const product = yield Product.findOne(productId); | ||
const user = yield User.findOne(userId) | ||
const card = yield CreditCards.findOneByUserId(userId) | ||
yield Charge.create({ | ||
customerId: user.customerId, | ||
source: card.source, | ||
price: product.price, | ||
}); | ||
return Promise.resolve(either.right({success: true})) | ||
} | ||
letAsyncEither(either) | ||
// we just got the error handling out of the way! | ||
.then(either.getOrElse(error => { | ||
switch(error.type) { | ||
// Just an idea, create your own abstraction for it. In ReasonML I do it with polymorphic variants. | ||
case 'user/findOneErr': return {error: 'Invalid user'} | ||
case 'product/findOneErr': return {error: 'Invalid product'} | ||
case 'card/findOneErr': return {error: 'Invalid card'} | ||
case 'charge/createErr': return {error: 'Failed to charge'} | ||
default: return {error: 'Something went terribly wrong'} | ||
} | ||
})) | ||
``` | ||
Basically if you build your code around those following some juice mathmagical laws you get better error handling for free. | ||
You could even create an async/await now for something like [Fluture](https://github.com/fluture-js/Fluture) which are much better than JS promises. |
19758
10
252