UNPKG

react-backend

Version:

A framework which help fetch data from backends and provide them to React.js components.

239 lines (191 loc) 7.06 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Base class for your DataProvider objects. */ var DataProvider = function () { /** * Constructor * At client side, will retrieve the preloaded data from window.data * so that there is no need to fetch data from backend * @returns {DataProvider} */ /** * This will hold a cache of the created promise objects, * in the form [ string => promise object ] */ /** Resolved values of the promises. Use getData() to access it */ function DataProvider() { var _this = this; _classCallCheck(this, DataProvider); this.values = {}; this.errors = {}; this.promises = {}; this._shouldReload = false; this.when = this.getPromise; this.pushNeeds = function (needs) { if (typeof needs === 'string') needs = [needs]; needs.forEach(function (promiseFuncName) { _this.getPromise(promiseFuncName); }); }; this.getData = function (need) { return _this.values[need]; }; this.getError = function (need) { return _this.errors[need]; }; this.hasErrors = function () { return Object.values(_this.errors).length > 0; }; if (typeof window !== 'undefined' && window.data) { Object.keys(window.data).forEach(function (key) { var value = window.data[key]; _this.promises[key] = Promise.resolve(value); _this.values[key] = value; }); } } /** * Builder and accessor function to get the promises managed by the DataProvider * @param {String} promiseName - name of the dataProvider function, such as "getUserComments" * @returns {Promise} - the associated promise */ /** will be true when some data need to be fetched from the backend */ /** Resolved errors of the promises. Use hasErrors() and getError() to access it */ _createClass(DataProvider, [{ key: 'getPromise', value: function getPromise(promiseName) { var promise = this.promises[promiseName]; if (!promise) { promise = this[promiseName](); this.promises[promiseName] = promise; this._shouldReload = true; } return promise; } /** * Use the when() function to express dependencies between your data. * If several promises share the same dependency, it will be cached and * called only one time. * Example : * getUserComments() { this.when("getUserId").then(id => db.fetchComments(id)) } */ /** * This is used internall by the NeedsData component. * @param {String or Object} needs - can be either the name of a function of your * dataProvider instance, or an array of names. * @returns {undefined} */ }, { key: 'resolveNeeds', /** * This will resolved all the promises, and populate the values and errors fields. * @returns {Promise} A promise resolving all the data needs. */ value: function resolveNeeds() { var self = this; // we store all the promises in the resolvers array // in such a way that they will always resolve (never reject) var resolvers = []; Object.values(this.promises).forEach(function (promise) { resolvers.push(promise.then(function (value) { promise.value = value; }, function (error) { promise.error = error; })); }); // and we resolve the array of promises return Promise.all(resolvers).then(function () { var values = {}; var errors = {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = Object.keys(self.promises)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var funcName = _step.value; var p = self.promises[funcName]; if (p.value) values[funcName] = p.value; if (p.error) errors[funcName] = p.error; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } self.values = values; self.errors = errors; self._shouldReload = false; }); } /** * Will force the data to be fetched again from the backend during the next * UI refresh * @param {String or Object} needs - can be either the name of a function of your * dataProvider instance, or an array of names. * @returns {undefined} */ }, { key: 'invalidate', value: function invalidate(needs) { if (typeof needs === 'string') needs = [needs]; var self = this; needs.forEach(function (need) { delete self.promises[need]; delete self.values[need]; delete self.errors[need]; }); } /** * Will invalidate all the data, in order to force reload during the next UI * refresh * @returns {undefined} */ }, { key: 'invalidateAll', value: function invalidateAll() { this.promises = {}; this.values = {}; this.errors = {}; this._shouldReload = false; } /** * @returns {bool} - will return true when there are unresolved needs which must be * fetched from the backend */ }, { key: 'shouldReload', value: function shouldReload() { return this._shouldReload; } /** * Use this to get the values of the data * @param {String} need - the name of the dataProvider function * @returns {DataProvider.values} - will return undefined if there was errors */ /** * Use this to get the error triggered when retrieving data * @param {String} need - the name of the dataProvider function * @returns {DataProvider.errors} - will return undefined if there was no error */ /** * @returns {Boolean} true if there are some errors */ }]); return DataProvider; }(); exports.default = DataProvider;