UNPKG

@danielkalen/simplybind

Version:

Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.

119 lines (99 loc) 2.68 kB
import { DOM, FEATURE } from 'aurelia-pal'; let hasSetImmediate = typeof setImmediate === 'function'; function makeRequestFlushFromMutationObserver(flush) { let toggle = 1; let observer = DOM.createMutationObserver(flush); let node = DOM.createTextNode(''); observer.observe(node, { characterData: true }); return function requestFlush() { toggle = -toggle; node.data = toggle; }; } function makeRequestFlushFromTimer(flush) { return function requestFlush() { let timeoutHandle = setTimeout(handleFlushTimer, 0); let intervalHandle = setInterval(handleFlushTimer, 50); function handleFlushTimer() { clearTimeout(timeoutHandle); clearInterval(intervalHandle); flush(); } }; } function onError(error, task) { if ('onError' in task) { task.onError(error); } else if (hasSetImmediate) { setImmediate(() => { throw error; }); } else { setTimeout(() => { throw error; }, 0); } } export let TaskQueue = class TaskQueue { constructor() { this.microTaskQueue = []; this.microTaskQueueCapacity = 1024; this.taskQueue = []; if (FEATURE.mutationObserver) { this.requestFlushMicroTaskQueue = makeRequestFlushFromMutationObserver(() => this.flushMicroTaskQueue()); } else { this.requestFlushMicroTaskQueue = makeRequestFlushFromTimer(() => this.flushMicroTaskQueue()); } this.requestFlushTaskQueue = makeRequestFlushFromTimer(() => this.flushTaskQueue()); } queueMicroTask(task) { if (this.microTaskQueue.length < 1) { this.requestFlushMicroTaskQueue(); } this.microTaskQueue.push(task); } queueTask(task) { if (this.taskQueue.length < 1) { this.requestFlushTaskQueue(); } this.taskQueue.push(task); } flushTaskQueue() { let queue = this.taskQueue; let index = 0; let task; this.taskQueue = []; try { while (index < queue.length) { task = queue[index]; task.call(); index++; } } catch (error) { onError(error, task); } } flushMicroTaskQueue() { let queue = this.microTaskQueue; let capacity = this.microTaskQueueCapacity; let index = 0; let task; try { while (index < queue.length) { task = queue[index]; task.call(); index++; if (index > capacity) { for (let scan = 0, newLength = queue.length - index; scan < newLength; scan++) { queue[scan] = queue[scan + index]; } queue.length -= index; index = 0; } } } catch (error) { onError(error, task); } queue.length = 0; } };