README
Declarative-Optional
A Javascript library to write concise functional code.Combined with features of Java Optional & Promise chaining
Features
Lazily evaluated
Merging multiple Optionals
Convert to Stream
chaining async and sync functions
Most of the Java Optional Features
Installation
npm install declarative-optional
Usage
// Common JS
const Optional = require( "declarative-optional");
//ES6
import Optional from "declarative-optional";
//Increment a Number , which may be null
Optional.of(input)
.map(val=>val+1)
.get()
// All the expressions will be evaluated only after you specified get()
//Increment a Number by 5, Only if its dividable by 5
Optional.of(input)
.filter(val=>val % 5 == 0)
.map(val=>val+5)
.get()
On Asynchronous code
// Consider the async function
function getFromUserService({username, password}) {
return new Promise((function (resolve) {
resolve({name: "user", isAdmin: true})
}))
}
async function login({username, password}) {
if (null == username || null == password) {
throw new Error("Cannot be Null")
}
const result = await getFromUserService(username, password)
if (result.isAdmin) {
redirectTo("adminPage")
} else {
redirectTo("userPage")
}
}
// With Declarative Optional
async function login({username, password}) {
const page = await Optional.of({username: user, password: pass})
.filter(({username, password}) => (null != username && null != password))
.map(getFromUserService)
.map(result => result.isAdmin ? "adminPage" : "userPage")
.toAsync();
page.ifPresentOrElse(redirectTo, () => {
throw new Error("Cannot be Null")
})
}
fetch Api with Optional
// Typical code
const url ='https://jsonplaceholder.typicode.com/todos/' + item
const rawResults = await fetch(url);
const response = await rawResults.json();
if (response.completed) {
return response.title
} else {
return null
}
// Can be rewritten with optional as
return await Optional.of('https://jsonplaceholder.typicode.com/todos/' + item)
.map(fetch)
.map(response => response.json())
.filter(response => response.completed == true)
.map(response => response.title)
.getAsync();
There are so much you can play with declarative Optional. It does have some features similar to Java Optional & RX libraries, except the code is small (one file around 4 Kb original source) and simple.
Documentation
Function | Description | Example |
Optional.of | To create a new Optional .Can be value or promise or null or undefined |
|
map | convert from one form to other, returns optional instance, can return async functions as well |
|
filter | apply a predicate function over a value |
|
flatmap | if an existing function returns Optional , it will flatten the value and pass it below |
|
get | evaluate all the chained functions and give the result. If no value is available , will return null |
Error
|
orElse | Evaluate all the chained functions and if result exists, give the result. If no value is available , will return value passed by |
|
stream | Evaluates all the chained functions and give an array object , if the result is already an array, it will provide as it is , if its single element, it converts to an array of single element |
|
getAsync |
Evaluate all the chained functions combined with promises give another Promise<result> |
The below will also work fine
|
toAsync |
Evaluate all the chained functions combined with promises give another Promise<Optional> which hold the response. All the async based results must use toAsync and then they can use the Optional consolidation functions , get ,orElse,stream etc.. |
|
Alternatives
There are some alternatives , Have a look into them as well