`fetchable` is a library for explicitly handling errors and loading in Typescript and JavaScript.
npm install @attio/fetchablefetchable is a library for explicitly handling errors and loading in Typescript and JavaScript.
sh
> npm install @attio/fetchable
`
Concepts
$3
There are three primitive states in fetchable.
#### ✅ Complete
A Complete is a simple JavaScript object which represents any kind of intact data.
`typescript
import {complete} from "@attio/fetchable"
const completeNumber = complete(1) // Returns a Complete<1>
console.log(completeNumber.value) // 1
console.log(completeNumber.state) // "complete"
`
#### ❌ Errored
An Errored is another JavaScript object which represents something that went wrong.
`typescript
import {errored} from "@attio/fetchable"
const erroredThing = errored("Oops") // Returns an Errored<"Oops">
console.log(erroredThing.error) // "Oops"
console.log(erroredThing.state) // "errored"
`
#### ⏳ Pending
A Pending is another JavaScript object which represents some process which is in progress.
`typescript
import {pending} from "@attio/fetchable"
const pendingThing = pending() // Returns a Pending
console.log(pendingThing.state) // "pending"
`
$3
The fun comes when we start to mix up the three primitive states.
#### Result: Complete or Errored
A Result is an object which is either a Complete or an Errored. It represents the
outcome of a process which might succeed or fail.
`typescript
import {isComplete} from "@attio/fetchable"
const result = doSynchronousThingWhichMightError() // Returns Result
if (isComplete(result)) {
console.log(result.value) // number
} else {
console.log(result.error) // "Oops"
}
`
#### Loadable: Complete or Pending
A Loadable is an object which is either a Complete or a Pending. It represents the
outcome of an asynchronous process which cannot fail.
`typescript
import {isComplete} from "@attio/fetchable"
const loadable = getStatusOfLongRunningProcess() // Returns Loadable
if (isComplete(loadable)) {
console.log(loadable.value) // number
}
`
#### Fetchable: Complete or Pending or Errored
A Fetchable is an object which is either a Complete, Errored or Pending. It
represents the outcome of an asynchronous process which can fail.
Fetchable is most often seen in declarative front-end code where we don't want to expose promises.
`typescript
import {isComplete, isErrored} from "@attio/fetchable"
const fetchable = getStatusOfLongRunningProcessWhichMightFail() // Returns Fetchable
if (isComplete(fetchable)) {
console.log(fetchable.value) // number
} else if (isErrored(fetchable)) {
console.log(fetchable.error) // "Oops"
}
`
#### AsyncResult
An AsyncResult is a promise of a Result. Complete, Errored or Pending.
It is most often seen in imperative code where we use promises for asynchronous processes.
`typescript
import {isComplete, isErrored} from "@attio/fetchable"
const asyncResult = runAsyncProcessWhichMightFail() // Returns AsyncResult
asyncResult.then(result => {
if (isComplete(result)) {
console.log(result.value) // number
} else if (isErrored(result)) {
console.log(result.error) // "Oops"
}
})
`
$3
fetchable provides functional utilities for working with these objects without explicitly checking
which state they're in.
#### map
`typescript
import {map} from "@attio/fetchable"
const fetchable = getStatusOfLongRunningProcessWhichMightFail() // Returns Fetchable
// Increments the fetchable if it's complete.
// Returns Fetchable
const incrementedFetchable = map(fetchable, (number) => number + 1)
`
#### bind
`typescript
import {map} from "@attio/fetchable"
const fetchable = getStatusOfLongRunningProcessWhichMightFail() // Returns Fetchable
// Increments the fetchable if it's complete and not zero.
// Returns Fetchable
const incrementedFetchable = bind(fetchable, (number) =>
number === 0 ? errored("Unexpected zero") : complete(number + 1)
)
`
#### combine
Arrays
`typescript
import {combine} from "@attio/fetchable"
const fetchable1 = getStatusOfLongRunningProcessWhichMightFail() // Returns Fetchable
const fetchable2 = doSynchronousThingWhichMightError() // Returns Result
// If both fetchables are complete then their values will be returned in a complete array.
// Returns Fetchable<[number, string], "Oops" | "Eek">
const combinedFetchable = combine([fetchable1, fetchable2])
`
Objects
`typescript
import {combine} from "@attio/fetchable"
const fetchableA = getStatusOfLongRunningProcessWhichMightFail() // Returns Fetchable
const fetchableB = doSynchronousThingWhichMightError() // Returns Result
// If both fetchables are complete then their values will be returned in a new object.
// Returns Fetchable<{a: number, b: string}, "Oops" | "Eek">
const combinedFetchable = combine({a: fetchable1, b: fetchable2})
`
#### combineAsync
Like Promise.all for AsyncResults. It takes multiple AsyncResults and resolves when they all
resolve with Completes or when one resolves with an Errored.
Arrays
`typescript
import {combineAsync} from "@attio/fetchable"
const asyncResult1 = runAsyncProcessWhichMightFail() // Returns AsyncResult
const asyncResult2 = runAnotherAsyncProcessWhichMightFail() // Returns AsyncResult
// Returns Result<[number, string], "Oops" | "Eek">
const combinedResult = await combineAsync([asyncResult1, asyncResult2])
`
Objects
`typescript
import {combine} from "@attio/fetchable"
const asyncResultA = runAsyncProcessWhichMightFail() // Returns AsyncResult
const asyncResultB = runAnotherAsyncProcessWhichMightFail() // Returns AsyncResult
// If both fetchables are complete then their values will be returned in a new object.
// Returns Result<{a: number, b: string}, "Oops" | "Eek">
const combinedResult = await combineAsync({a: asyncResultA, b: asyncResultB})
``