Sawtaytoes
12/11/2018 - 10:53 PM

Double-Emitting Promise Implementation

And example implementation of a double-emitting promise as the CachedDataFetcher class.

class CachedDataFetcher {
  static create(...args) {
    return new CachedDataFetcher(...args)
  };

  constructor({
    url,
  }) {
    this
    .url = url

    this
    .dataHandlers = []

    this
    .activateDataHandlers = (
      this
      .activateDataHandlers
      .bind(this)
    )

    this
    .fetchData = (
      this
      .fetchData
      .bind(this)
    )

    this
    .storeResponseInCache = (
      this
      .storeResponseInCache
      .bind(this)
    )
  }

  activateDataHandlers(data) {
    if (data === this.cachedData) {
      return null
    }

    this
    .cachedData = data

    this
    .dataHandlers
    .reduce(
      (
        returnValue,
        dataHandler,
      ) => (
        dataHandler(
          data
        )
      ),
      data,
    )

    return data
  }

  done() {
    this
    .fetchCache()
  }

  fetchCache() {
    return (
      caches
      .match(this.url)
      .then(response => (
        response
        && (
          response
          .text()
        )
      ))
      .then(this.activateDataHandlers)
      .then(this.fetchData)
    )
  }

  fetchData() {
    return (
      fetch(this.url)
      .then(this.storeResponseInCache)
      .then(response => (
        response
        .clone()
        .text()
      ))
      .then(this.activateDataHandlers)
    )
  }

  storeResponseInCache(response) {
    caches
    .open('v1')
    .then(cache => (
      cache
      .put(
        this.url,
        response,
      )
    ))

    return response
  }

  then(dataHandler) {
    this
    .dataHandlers
    .push(dataHandler)

    return this
  }
}