UNPKG

bifur

Version:

A library providing simple use of asynchronous functionality via Web Workers.

242 lines (230 loc) 8.34 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["Bifur"] = factory(); else root["Bifur"] = factory(); })(self, function() { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // EXPORTS __webpack_require__.d(__webpack_exports__, { "default": () => (/* binding */ Bifur) }); ;// CONCATENATED MODULE: ./src/Worker/Builder.ts /** Class used for building Worker instances. */ class Builder { /** * Build an instance of Worker containing function supplied. * @param window {Window} The relative Window object. * @param fnc {Function} Function to run inside the Worker. * @returns {Worker} The Worker instance. */ static build(window, fnc) { const blob = Builder.generateBlob(fnc); const blobUrl = window.URL.createObjectURL(blob); return new Worker(blobUrl); } /** * Compose the content intended for the Worker's Blob. * @param fnc {Function} The function to be run inside the Worker. * @returns {string} The intended content for a Blob. */ static generateBlobContent(fnc) { return ` self.onmessage = function(m) { const requestId = m.data.requestId; const output = (${fnc.toString()})(...m.data.input); self.postMessage({ requestId, output }); }; `; } /** * Generate a Blob in order to construct the Worker. * @param fnc {Function} The function to be run inside the Worker. * @returns {Blob} The Blob used to construct the Worker. */ static generateBlob(fnc) { const blobContent = Builder.generateBlobContent(fnc); return new Blob([blobContent], { type: 'application/javascript' }); } } ;// CONCATENATED MODULE: ./src/Helpers/generateUUID.ts /** * Generates a UUID. * @returns {string} a uuid. */ function generateUUID() { let d = new Date().getTime(); let d2 = (performance && performance.now && (performance.now() * 1000)) || 0; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { let r = Math.random() * 16; if (d > 0) { r = (d + r) % 16 | 0; d = Math.floor(d / 16); } else { r = (d2 + r) % 16 | 0; d2 = Math.floor(d2 / 16); } return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16); }); } ; ;// CONCATENATED MODULE: ./src/Worker/PersistentWrapper.ts /** Class used to create a persistent wrapper function for a Worker. */ class PersistentWrapper { constructor(worker) { this.requests = []; this.worker = worker; this.worker.onmessage = e => this.resolveRequest(e); this.worker.onmessageerror = e => this.rejectRequest(e); this.worker.onerror = e => this.rejectRequest(e); } /** * Get the request respective of the response from the worker. * @param event the MessageEvent from the worker. * @returns {Request} */ getRequest(event) { const request = this.requests.find(r => event.data.requestId === r.requestId); if (request) { const requestIndex = this.requests.indexOf(request); this.requests.splice(requestIndex, 1); return request; } console.error('Could not find request:', event.data.requestId, event); } /** * Run the respective request's resolve function * and pass it the data returned from the worker. * @param event the MessageEvent from the worker. */ resolveRequest(event) { const request = this.getRequest(event); request.resolve(event.data.output); } /** * Run the respective request's reject function * and pass it the event from the worker. * @param event the MessageEvent from the worker. */ rejectRequest(event) { const request = this.getRequest(event); request.reject(event); } /** * Runs the worker function and returns a promise to await for results. * @param input an array of arguments intended for the worker function. * @returns {Promise} that resolves (or rejects) when the function completes. */ run(input) { const requestId = generateUUID(); return new Promise((resolve, reject) => { this.requests.push({ requestId, resolve, reject }); this.worker.postMessage({ requestId, input }); }); } /** * Teardown the PersistentWorker, terminating the worker and * removing any references to the previous requests. */ teardown() { this.worker.terminate(); this.requests = []; } } ;// CONCATENATED MODULE: ./src/Worker/Wrapper.ts /** Class used to create a wrapper function for a Worker. */ class Wrapper { /** * Wrap a Worker into a function returning a Promise, resolving when the Worker has responded. * @param worker {Worker} The worker to be wrapped. * @returns {Function} A function that returns a Promise, resolving when the Worker responds. */ static wrap(worker) { return (input) => { return new Promise((resolve, reject) => { const requestId = generateUUID(); worker.onmessage = (event) => { if (event.data.requestId === requestId) { resolve(event.data.output); worker.terminate(); } }; worker.onmessageerror = (event) => { reject(event); worker.terminate(); }; worker.onerror = (event) => { reject(event); worker.terminate(); }; worker.postMessage({ requestId, input }); }); }; } } ;// CONCATENATED MODULE: ./src/Bifur.ts /** Class allowing asynchronous functionality via a Worker. */ class Bifur { /** * Run the supplied function with the supplied arguments asynchronously. * @param fnc {Function} The function to be run asynchronously. * @param args {Array} The arguments to pass to the function. * @returns {Promise} The promise that resolves once the function has completed. */ static run(fnc, args) { const worker = Builder.build(window, fnc); const wrapper = Wrapper.wrap(worker); const result = wrapper(args); return result; } /** * Create a persistent worker wrapped in a class allowing the user to run * a function asynchronously, and even store a state within the function. * @param fnc {Function} The function to be run asynchronously. * @returns {PersistentWrapper} An instance of the class PersistentWrapper. */ static persist(fnc) { const worker = Builder.build(window, fnc); const wrapper = new PersistentWrapper(worker); return wrapper; } } __webpack_exports__ = __webpack_exports__["default"]; /******/ return __webpack_exports__; /******/ })() ; }); //# sourceMappingURL=index.js.map