Skip to content

qiwi/inside-out-promise

Repository files navigation

inside-out-promise

Produces promises with chainable resolvers and observable state.

Build Status David Maintainability Test Coverage npm

Install

npm add inside-out-promise
yarn add inside-out-promise

Key features

  • Chainable resolve and reject methods
  • Exposed promise state and result fields
  • Configurable Promise implementation
  • TS and Flow typings out of box

Usage

import {factory} from 'inside-out-promise'

const promise = factory() // produces a promise
promise.then((data) => {  // standard `thenable` iface
  doSomething(data)
})

const data = await fetch({...})
promise.resolve(data)     // internal resolver is exposed as public promise field
promise.result            // data ref
promise.value             // same data ref, result alias
promise.state             // 'Fulfilled'
promise.status            // status alias: 'Fulfilled'
promise.isPending()       // false
promise.isFulfilled()     // true
promise.isResolved()      // true

// Or the same in OOP style
import {InsideOutPromise} from 'inside-out-promise'
const p = new InsideOutPromise()

API

Resolvers

Both executor args — resolve and reject — are available as chainable public methods:

const promise = factory()

promise.resolve('foo')            // This's a promise
promise.reject(new Error('bar'))  // and this is too

Chains

factory().resolve('value').then(data => {
  // here's the value: data === 'value'
})

factory().catch(error => {
  // the error goes here
}).reject(new Error())

You're able to combine steps in Java-like style: first build the "CompletableFuture" chain and resolve it after

const p = new InsideOutPromise()
  .then(data => data.repeat(2))
    .then(data => data.toUpperCase())
      .then(data => data + 'bar')
        .resolve('foo')

const res = await p // 'FOOFOObar'

Each step return InsideOutPromise instance inherited from Promise, Bluebird (see Configuration for details), etc, so the intanceof check still works.

const p1 = new InsideOutPromise()
const p2 = p1.then(data => data)

const v1 = await(p1)
const v2 = await(p2)

expect(p1).toBeInstanceOf(Promise)
expect(p2).toBeInstanceOf(Promise)
expect(p1).toBeInstanceOf(InsideOutPromise)
expect(p2).toBeInstanceOf(InsideOutPromise)

State

Promise state field may take values: Pending, Fulfilled and Rejected

const promise = factory()
promise.state // 'Pending'

promise.resolve()
promise.state // 'Fulfilled'

There're also 3 helper methods:

  • isPending()
  • isRejected()
  • isFulfilled()

InsideOutPromise

import InsideOutPromise from 'inside-out-promise'

const promise = new InsideOutPromise((resolve, reject) => {
  // Legacy executor flow is still supported
  // ...
})

promise.resolve('foo')
promise.then(data => console.log(data)) // It's `foo`

Configuration

import factory from 'inside-out-promise'
import * as Bluebird from 'bluebird'

factory.Promise = Bluebird // Native `Promise` by default

Refs