GithubHelp home page GithubHelp logo

hartl3y94 / declarative-optional Goto Github PK

View Code? Open in Web Editor NEW

This project forked from muthuishere/declarative-optional

0.0 0.0 0.0 519 KB

A Declarative way to deal with null , undefined and promises via optional and streams

License: MIT License

JavaScript 0.49% TypeScript 99.51%

declarative-optional's Introduction

Build Coverage License Version

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]
    

Documentation

Function Description Example
Optional.of To create a new Optional .Can be value or promise or null or undefined
 Optional.of(input)

map convert from one form to other, returns optional instance, can return async functions as well
  Optional.of(21)
  .map(val => val + 1)

filter apply a predicate function over a value
  Optional.of(21)
  .filter(val => val % 5 == 0)

flatmap if an existing function returns Optional , it will flatten the value and pass it below
// Consider a function which will return Optional
//returns Optional 
const powersOf = (name)=>Optional.of(['web-shooters','syntheitic-webbing'])

const superHeroById = (id) =>  "Spider-Man"

const res  = Optional.of(52001)
    .map(superHeroById)
    .map(powersOf )
    .flatten()
    .get()

// results ['web-shooters','syntheitic-webbing']

const res  = Optional.of(52001)
    .map(superHeroById)
    .flatmap(powersOf )
    .get()

// results ['web-shooters','syntheitic-webbing']

get evaluate all the chained functions and give the result. If no value is available , will return null
  Optional.of(21)
  .filter(val => val % 5 == 0)
  .map(val => val + 5)
  .get() ;  // returns null

  Optional.of(20)
  .filter(val => val % 5 == 0)
   .map(val => val + 5)
  .get() ;  // returns 25

Error

  Optional.of(input)      
   .map(promiseFunctionToValidateUserDetails)
   .map(promiseFunctionToValidateSomeOther)
  .get() ;  

// Error ? Use getAsync to deal with promises

orElse Evaluate all the chained functions and if result exists, give the result. If no value is available , will return value passed by
  Optional.of(21)
  .filter(val => val % 5 == 0)
  .map(val => val + 5)
  .orElse(45) ;  // returns 45 , as the evaluation will return null

  Optional.of(20)
  .filter(val => val % 5 == 0)
   .map(val => val + 5)
  .orElse(45) ;  // returns 25

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
const res  = Optional.of([23,45])
    .stream()
    .map(i=>i+1);

//returns [24,46]

const res  = Optional.of(null)
    .stream()
    .map(i=>i+1);

//returns []

const res  = Optional.of(23)
    .stream()
    .map(i=>i+1);

//returns [24]

getAsync
Evaluate all the chained functions combined with promises give another Promise<result>

 const result = await Optional.of(input)      
               .map(promiseFunctionToValidateUserDetails)
               .map(promiseFunctionToValidateRole)
                .map(regularFunctionToFormatData)
                .getAsync()

const result = 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();

The below will also work fine

  const result = await Optional.of(21)
                          .filter(val => val % 5 == 0)
                          .map(val => val + 5)
                          .getAsync()  

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..

  Optional.of(input)      
   .map(promiseFunctionToValidateUserDetails)
   .map(promiseFunctionToValidateSomeOther)
  .toAsync()
   .then(optionalData=>{
        // optionalData.get() holds the result
    })

 const optionalData = await Optional.of(input)      
                   .map(promiseFunctionToValidateUserDetails)
                   .map(promiseFunctionToValidateSomeOther)
                  .toAsync()

// optionalData.get() holds the result

Alternatives

There are some alternatives , Have a look into them as well

Optional.js

amidevtech/optional.js

declarative-optional's People

Contributors

muthuishere avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.