Skip to content

Instantly share code, notes, and snippets.

@micha149
Last active March 19, 2018 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save micha149/d75bc843215572c02855263971bfff88 to your computer and use it in GitHub Desktop.
Save micha149/d75bc843215572c02855263971bfff88 to your computer and use it in GitHub Desktop.
Functional, static typed, promised approach for handling async stuff
type Arity1<A, B> = (a: A) => Promise<B>;
function asyncPipe<A, B>(f: Arity1<A, B>): Arity1<A, B>;
function asyncPipe<A, B, C> (g: Arity1<A, B>, f: Arity1<B, C>): Arity1<A, C>;
function asyncPipe<A, B, C, D> (h: Arity1<A, B>, g: Arity1<B, C>, f: Arity1<C, D>): Arity1<A, D>;
function asyncPipe<A, B, C, D, E> (i: Arity1<A, B>, h: Arity1<B, C>, g: Arity1<C, D>, f: Arity1<D, E>): Arity1<A, E>;
function asyncPipe<A, B, C, D, E, F> (j: Arity1<A, B>, i: Arity1<B, C>, h: Arity1<C, D>, g: Arity1<D, E>, f: Arity1<E, F>): Arity1<A, F>;
export default function asyncPipe (...fns) {
return x => fns.reduce(async (y, f) => f(await y), x);
}
import asyncPipe from './asyncPipe';
interface Burger {
name: string,
}
interface Server {
getMaximumNumberOfBurgersPerDay():Promise<Number>,
hasBurgers():Promise<boolean>,
loadBurger():Promise<Burger>,
}
interface HandlerData {
defaultBurger: Burger,
burger?: Burger,
hasBurgers?: boolean,
maxDailyBurgerExceeded?: boolean,
}
const getNumberOfEatenBurgersToday = () => 6;
const checkAvailability = (server: Server) => async (data: HandlerData): Promise<HandlerData> =>
server.hasBurgers()
.then(hasBurgers => ({ ...data, hasBurgers}));
const checkDailyConsume = (server: Server) => async (data: HandlerData): Promise<HandlerData> =>
server.getMaximumNumberOfBurgersPerDay()
.then(max => ({ ...data, maxDailyBurgerExceeded: getNumberOfEatenBurgersToday() >= max }))
const eventuallyResolveBurger = (server: Server) => async (data: HandlerData): Promise<Burger> =>
data.hasBurgers && !data.maxDailyBurgerExceeded
? server.loadBurger()
: Promise.resolve(data.defaultBurger);
const getHamburger = server => asyncPipe<HandlerData, HandlerData, HandlerData, Burger>(
checkAvailability(server),
checkDailyConsume(server),
eventuallyResolveBurger(server),
);
import getHamburger from './getHamburger';
const myServer = {
getMaximumNumberOfBurgersPerDay():Promise<Number> {
return Promise.resolve(50);
},
hasBurgers():Promise<boolean> {
return Promise.resolve(true);
},
loadBurger():Promise<Burger> {
return Promise.resolve({ name: 'BugMac' });
}
};
const defaultBurger = { name: 'AppleMac' };
getHamburger(myServer)({ defaultBurger })
.then(burger => console.log(burger));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment