UNPKG

react-imported-component

Version:
124 lines (123 loc) 4.25 kB
import { isBackend } from '../utils/detectBackend'; import { getFunctionSignature, importMatch } from '../utils/signatures'; import { assignLoadableMark } from './marks'; import { addPending, removeFromPending } from './pending'; import { getPreloaders } from './preloaders'; import { LOADABLE_SIGNATURE } from './registry'; import { toKnownSignature } from './utils'; export function toLoadable(firstImportFunction, autoImport = true) { let importFunction = firstImportFunction; const loadImportedComponent = () => Promise.all([importFunction(), ...getPreloaders()]).then(([result]) => result); const functionSignature = getFunctionSignature(importFunction); const mark = importMatch(functionSignature); let resolveResolution; const resolution = new Promise((r) => { resolveResolution = r; }); const loadable = { // importFunction, mark, resolution, done: false, ok: false, error: null, payload: undefined, promise: undefined, isLoading() { return !!this.promise && !this.done; }, reset() { this.done = false; this.ok = true; this.payload = undefined; this.promise = undefined; }, replaceImportFunction(newImportFunction) { importFunction = newImportFunction; }, get importer() { return importFunction; }, then(cb, err) { if (this.promise) { return this.promise.then(cb, err); } if (err) { err(); } return Promise.reject(); }, loadIfNeeded() { if (this.error) { this.reset(); } if (!this.promise) { this.load(); } return this.promise; }, tryResolveSync(then) { if (this.done) { const result = then(this.payload); return { then(cb) { // synchronous thenable - https://github.com/facebook/react/pull/14626 cb(result); return Promise.resolve(result); }, }; } return this.loadIfNeeded().then(then); }, reload() { if (this.promise) { this.promise = undefined; return this.load(); } return Promise.resolve(); }, _probeChanges() { return Promise.resolve(importFunction()) .then((payload) => payload !== this.payload) .catch((err) => { throw err; }); }, load() { if (!this.promise) { const promise = (this.promise = loadImportedComponent().then((payload) => { this.done = true; this.ok = true; this.payload = payload; this.error = null; removeFromPending(promise); resolveResolution(payload); return payload; }, (err) => { this.done = true; this.ok = false; this.error = err; removeFromPending(promise); throw err; })); addPending(promise); } return this.promise; }, }; if (mark && mark.length) { LOADABLE_SIGNATURE.set(toKnownSignature(functionSignature, mark), loadable); assignLoadableMark(mark, loadable); } else { if (process.env.NODE_ENV !== 'development') { // tslint:disable-next-line:no-console console.warn('react-imported-component: no mark found at', importFunction, "Please check babel plugin or macro setup, as well as imported-component's limitations. See https://github.com/theKashey/react-imported-component/issues/147"); } } // trigger preload on the server side if (isBackend && autoImport) { loadable.load(); } return loadable; }