Last active
November 10, 2018 15:40
-
-
Save MikeBild/c912bc47380496e07a64 to your computer and use it in GitHub Desktop.
Async Railway Oriented Programming in JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/env node | |
//thx to http://fsprojects.github.io/Chessie/a-tale-of-3-nightclubs.html | |
Promise.all([ | |
suitablePersonEnterGayBar(), | |
unsuitablePersonEnterGayBar(), | |
]) | |
.then(result => result.map((person, i) => `Person ${i+1}: ${person.cost || ''}${person.reasons.join(' ')}`)) | |
.then(result => console.log(`Person entries\n${result.join('\n')}`)); | |
module. exports = () => { | |
return { | |
Person: Person, | |
enterGayBar: enterGayBar, | |
costToEnter: costToEnter, | |
checkClothes: checkClothes, | |
checkAge: checkAge, | |
checkGender: checkGender, | |
}; | |
}; | |
function suitablePersonEnterGayBar() { | |
return enterGayBar(new Person('Male', 24, ['Shirt'])); | |
} | |
function unsuitablePersonEnterGayBar() { | |
return enterGayBar(new Person('Male', 17, ['Tie'])); | |
} | |
function Person (gender, age, clothes, sobriety) { | |
this.gender = gender; | |
this.age = age; | |
this.clothes = clothes || []; | |
this.sobriety = sobriety | |
} | |
function enterGayBar (person) { | |
return costToEnter(person, [checkGender, checkAge, checkClothes]) | |
.then(data => ({cost: data, reasons: []})) | |
.catch(err => ({reasons: err})); | |
} | |
function costToEnter (person, rules) { | |
const initial = { | |
failures: [], | |
success: person.gender === 'Female' ? 0 : 5, | |
}; | |
return Promise | |
.all(rules.map(fn => fn(person).catch(err => err))) | |
.then(results => { | |
const result = results.reduce((state, result) => { | |
if(result.message) state.failures.push(result.message); | |
return state; | |
}, initial); | |
if(result.failures.length > 0) return Promise.reject(result.failures); | |
return Promise.resolve(result.success); | |
}); | |
} | |
function checkClothes (person) { | |
if(person.gender === 'Male' && person.clothes.indexOf('Tie') !== -1) return Promise.reject(new Error('Smarten up!')); | |
if(person.gender === 'Female' && person.clothes.indexOf('Trainers') !== -1) return Promise.reject(new Error('Smarten up!')); | |
return Promise.resolve(person); | |
} | |
function checkAge (person) { | |
if(person.age < 18) return Promise.reject(new Error('Too young!')); | |
if(person.age > 40) return Promise.reject(new Error('Too old!')); | |
return Promise.resolve(person); | |
} | |
function checkGender (person) { | |
if(person.gender === 'Female') return Promise.reject(new Error('Men only!')); | |
return Promise.resolve(person); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const assert = require('assert'); | |
const asyncEitherExample = require('./async-either-with-promise')(); | |
describe('Async either with promises', () => { | |
it('person (Male, 24, Shirt) should suitable', () => { | |
const person = new asyncEitherExample.Person('Male', 24, ['Shirt']); | |
return asyncEitherExample | |
.enterGayBar(person) | |
.then(actual => { | |
assert.equal(actual.cost, 5); | |
}); | |
}); | |
it('person (Male, 17, Tie) should unsuitable', () => { | |
const person = new asyncEitherExample.Person('Male', 17, ['Tie']); | |
return asyncEitherExample | |
.enterGayBar(person) | |
.then(actual => { | |
assert.deepEqual(actual.reasons, ['Too young!', 'Smarten up!']); | |
}); | |
}); | |
it('person (Female, 25, Trainers) should unsuitable', () => { | |
const person = new asyncEitherExample.Person('Female', 25, ['Trainers']); | |
return asyncEitherExample | |
.enterGayBar(person) | |
.then(actual => { | |
assert.deepEqual(actual.reasons, ['Men only!', 'Smarten up!']); | |
}); | |
}); | |
it('person (Male, 41) should unsuitable', () => { | |
const person = new asyncEitherExample.Person('Male', 41); | |
return asyncEitherExample | |
.enterGayBar(person) | |
.then(actual => { | |
assert.deepEqual(actual.reasons, ['Too old!']); | |
}); | |
}); | |
}); |
updated ;-)
๐
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
๐