Package Exports
- declarative-optional
- declarative-optional/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (declarative-optional) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Declarative-Optional
A Javascript library to write concise functional code.Combined with features of Java Optional & Javascripts Promise chaining
Features
Lazily evaluated
chaining async and sync functions
Most of the Java Optional Features
Some of the Java Stream Features
Installation
npm install declarative-optional
Usage
To Import
// Common JS
const {Optional} = require( "declarative-optional");
//ES6
import {Optional} from "declarative-optional";
Common Usages
//Increment By 5
function incrementByFive(input) {
return Optional.of(input)
.map(i=>i+5)
.orElse(0)
}
// incrementByFive(41) => 46
// incrementByFive(null) => 0
// incrementByFive(undefined) => 0
// 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 suite. 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.
It also features a stream library, a wrapper for array , with lazy evaluation and functional programming features.
//commonjs
const {Stream} = require("declarative-optional");
//ES6
import {Stream} from "declarative-optional";
const results = Stream.of([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.filter(val => val % 2 == 0)
.map(val => val * 2)
.get();
console.log(stream) // [4,8,12,16,20]
// first
Stream.of([45,46,80])
.first()
.get()
// [45]
// last
Stream.of([45,46,80])
.last()
.get()
// [80]
//The first and last methods are useful when you want to get the first or last element of a stream and also you can chain up map operations.
Stream.of([45,46,80])
.last()
.map(val=>val*2)
.get()
// [160]
// Async Stream
const input = [Promise.resolve(21),Promise.resolve(25),Promise.resolve(30)]
const result = await Stream.of(input)
.filter((value) => value %5 ==0)
.map(getFromUserService)
.getAsync()
// [25,30]
// handle async errors or empty values with default value
const input = [Promise.resolve(21),Promise.reject(25),Promise.resolve(30)]
const val = await Stream.of(input)
.filter((value) => value %5 ==0)
.map(getFromUserService)
.orElseAsync(["default"])
// ["default"]
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