Using JSData with Observables

When Promises aren't enough.

How-To Guides

Using JSData with Observables

TODO: short blurb about Promises vs Observables

JSData uses Promises to handle asynchronous operations, but if you prefer to work with Observables, here are several options:

Convert Promises to Observables

This example uses RxJS:

const store = new JSData.Container()
store.defineMapper('user')

const source = Rx.Observable.fromPromise(store.find('user', 1));

const subscription = source.subscribe(
  function (user) {
    console.log('Next: %s', user)
  },
  function (err) {
    console.log('Error: %s', err)
  },
  function () {
    console.log('Completed')
  }
)

You could also augment Promise.prototype with a convenience method:

// You can optionally tell JSData what "Promise" to use, e.g.:
// JSData.utils.Promise = require('bluebird')

// This gives you an Observable interface, but nothing else...
Object.defineProperty(
  // JSData uses global.Promise or window.Promise by default
  JSData.utils.Promise.prototype,
  'toObservable',
  {
    value () {
      return Rx.Observable.fromPromise(this)
    }
  }
)

const store = new JSData.Container()
store.defineMapper('user')

store
  .find('user', 1)
  .toObservable()
  .subscribe(
    function (user) {
      console.log('Next: %s', user)
    },
    function (err) {
      console.log('Error: %s', err)
    },
    function () {
      console.log('Completed')
    }
  )

Add a "subscribe" method to Promise.prototype

// You can optionally tell JSData what "Promise" to use, e.g.:
// JSData.utils.Promise = require('bluebird')

// This gives you an Observable interface, but nothing else.
// Probably not the best option...
Object.defineProperty(
  // JSData uses global.Promise or window.Promise by default
  JSData.utils.Promise.prototype,
  'subscribe',
  {
    value (onNext, onError, onComplete) {
      return this.then(function (result) {
        setTimeout(function () {
          onNext(result)
        }, 0)
        setTimeout(function () {
          onComplete()
        }, 0)
      }, onError)
    }
  }
)

const store = new JSData.Container()
store.defineMapper('user')

store
  .find('user', 1)
  .subscribe(
    function (user) {
      console.log('Next: %s', user)
    },
    function (err) {
      console.log('Error: %s', err)
    },
    function () {
      console.log('Completed')
    }
  )