This page is part of a static HTML representation of TriTarget.org at https://tritarget.org

DomainSpecificPromise

Sukima8th April 2018 at 7:45am

A Domain Specific Promise is a concept that I use to describe an object that has the same semantics as a Promise but is tailored to a specific domain. This means it has its own callback functions and a different set of resolutions that just fulfilled and rejected.

This concept has three main components:

  1. Constuctor/Resolver - A custom initializer function with hooks for each new resolution state
  2. Factory method - A utility factory method that is used to construct a new object based on just the payload provided. It will unwrap / proxy / prepare raw data and return a ready to chain Domain Specific Promise object
  3. Chainable API - Chainable callbacks for each resolution state which return new Domain Specific Promise objects so that the previous chain is not mutated

Constructor/Resolver

Like a Promise the constructor of the object takes an initializer function. This callback is executed immediately and is passed an object with hooks for each resolution state.

Each hook is a function that can take a value and has no ties to any this contexts so they can be passed around the app or attached to event handlers all without loosing any context.

Example

class Example {
  constructor(initFn) {
    this.promise = new Promise((resolve, reject) => {
      initFn({
        error: reject,
        resolveReason1: value => resolve({ reason: 'reason1', value }),
        resolveReason2: value => resolve({ reason: 'reason2', value }),
        resolveReason3: value => resolve({ reason: 'reason3', value })
      });
    });
  }
}

Factory method

The factory method is a static method that can take any of the following and know how to return a new instance of the Domain Specific Object. The idea is to unwrap the values construct new promise chain and return a new and well constructed DomainSpecificPromise.

Example

static resolve(result) {
  if (result instanceof DomainSpecificPromise) { return result; }
  let newDomainSpecificPromise = Object.create(DomainSpecificPromise.prototype);
  newDomainSpecificPromise.promise = Promise.resolve(result);
  return newDomainSpecificPromise;
}

Chainable API

Each resolution will have a callback. They will be a no-op if the resolution is not applicable and allow the chaining to continue. If it is applicable then the return value from the function will result in a new instance of a DomainSpecificPromise and llow continued chaining. It should be able to accept a scalar value, promise, or a new DomainSpecificPromise (to mutate the resolution if desired).

Example

onReason1(fn) {
  return DomainSpecificPromise.resolve(this.promise.then(result => {
    if (result.reason !== 'reason1') { return result; }
    let newValue = fn(result.value);
    if (newValue instanceof DomainSpecificPromise) { return newValue.promise; }
    return Promise.resolve(newValue).then(value => ({ reason: 'reason1', value }));
  }));
}