Manual Reference Source Test

src/loaders/JsonLoader.js

/**
*  @file JsonLoader.js
*  @author Liqueur de Toile <contact@liqueurdetoile.com>
*  @licence AGPL-3.0 {@link https://github.com/liqueurdetoile/beloader/blob/master/LICENSE}
*/

import AbstractLoader from 'core/AbstractLoader';

/**
*  Load and parse JSON data
*
*  JsonLoader only performs asynchronously. If succeeded, returned data
*  will be available in QueueItem#response property.
*
*  @version 1.0.0
*  @since 1.0.0
*  @author Liqueur de Toile <contact@liqueurdetoile.com>
*
*  @example
*  var loader = new Beloader();
*
*  loader
*   .fetch('json', 'https://reqres.in/api/users')
*   .then(function(item) {
*     var data = item.response; // JSON data
*   });
*
*/
export default class JsonLoader extends AbstractLoader {
  /**
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @param {QueueItem} parent QueueItem calling parent
  *  @param {DotObjectArray} options Options for loader
  */
  constructor(parent, options) {
    if (!options.has('url')) throw new TypeError('Beloader : Asset JSON url must be defined');
    super(parent, options);
    this.options.push('fallbackSync', false); // No sync fallback allowed
  }

  /**
  *  Always throw an error because method is not allowed
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @override
  *  @throws {TypeError} Always thrown if method requested
  */
  sync() {
    throw new TypeError('BeLoader : JsonLoader only works in async mode');
  }

  /**
  *  Event hook to add specific JSON request headers to
  *  XMLHttpRequest instance
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  */
  _loadstart() {
    this.xhr.setRequestHeader('Accept', 'application/json');
    this.xhr.responseType = 'json';
  }

  /**
  *  Async loader for JSON data
  *
  *  The loader will first try to fetch parsed JSON, then try to parse
  *  response itself and finally try to parse responseText for IE.
  *
  *  If none of parsing succeeds, promise is rejected.
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @returns {Promise}
  */
  async() {
    const _this = this;

    return new Promise((resolve, reject) => {
      super.async().then(
        response => {
          let rejected = false;
          let err = 'Beloader : Malformed JSON or non-JSON';

          // IE Hack or null response
          if (typeof response === 'undefined' || response === null) {
            try {
              response = this.xhr.responseText;
            } catch (e) {
              rejected = true;
            }
          }

          //
          /* istanbul ignore next */
          if (typeof response === 'string') {
            try {
              response = JSON.parse(response);
            } catch (error) {
              rejected = true;
              err = error;
            }
          }

          if (rejected) {
            reject(err);
          } else {
            _this.parent.response = response;
            resolve();
          }
        },
        error => {
          reject(error);
        }
      );
    });
  }
}

export {JsonLoader};