UNPKG

ember-concurrency

Version:

Improved concurrency/async primitives for Ember.js

106 lines (101 loc) 4.2 kB
import { assert } from '@ember/debug'; import { get } from '@ember/object'; import { addListener } from '@ember/object/events'; import { addObserver } from '@ember/object/observers'; import { scheduleOnce } from '@ember/runloop'; import { registerModifier, TaskFactory as TaskFactory$1 } from './external/task-factory.js'; import { EncapsulatedTask, Task } from './task.js'; import { TaskProperty } from './task-properties.js'; import { TaskGroup } from './task-group.js'; import EmberScheduler from './scheduler/ember-scheduler.js'; import { EMBER_ENVIRONMENT } from './ember-environment.js'; let handlerCounter = 0; function registerOnPrototype(addListenerOrObserver, proto, names, taskName, taskMethod, once) { if (names && names.length > 0) { for (let i = 0; i < names.length; ++i) { let name = names[i]; let handlerName = `__ember_concurrency_handler_${handlerCounter++}`; proto[handlerName] = makeTaskCallback(taskName, taskMethod, once); addListenerOrObserver(proto, name, null, handlerName); } } } function makeTaskCallback(taskName, method, once) { return function () { let task = get(this, taskName); if (once) { scheduleOnce('actions', task, method, ...arguments); } else { task[method].apply(task, arguments); } }; } const ensureArray = possibleArr => Array.isArray(possibleArr) ? possibleArr : [possibleArr]; registerModifier('cancelOn', (factory, eventNames) => factory.addCancelEvents(...ensureArray(eventNames))); registerModifier('observes', (factory, propertyPaths) => factory.addObserverKeys(...ensureArray(propertyPaths))); registerModifier('on', (factory, eventNames) => factory.addPerformEvents(...ensureArray(eventNames))); class TaskFactory extends TaskFactory$1 { env = EMBER_ENVIRONMENT; createTask(context) { assert(`Cannot create task if a task definition is not provided as generator function or encapsulated task.`, this.taskDefinition); let options = this.getTaskOptions(context); if (typeof this.taskDefinition === 'object') { return new EncapsulatedTask(Object.assign({ taskObj: this.taskDefinition }, options)); } else { return new Task(Object.assign({ generatorFactory: args => this.taskDefinition.apply(context, args) }, options)); } } createTaskGroup(context) { assert(`A task definition is not expected for a task group.`, !this.taskDefinition); let options = this.getTaskOptions(context); return new TaskGroup(options); } addCancelEvents(...cancelEventNames) { this._cancelEventNames = this._cancelEventNames || []; this._cancelEventNames.push(...cancelEventNames); return this; } addObserverKeys(...keys) { this._observes = this._observes || []; this._observes.push(...keys); return this; } addPerformEvents(...eventNames) { this._eventNames = this._eventNames || []; this._eventNames.push(...eventNames); return this; } getModifier(name) { let modifier = super.getModifier(name); if (!modifier && typeof TaskProperty.prototype[name] === 'function') { // Shim for compatibility with user-defined TaskProperty prototype // extensions. To be removed when replaced with proper public API. modifier = TaskProperty.prototype[name].bind(this); } assert(`Task option '${name}' is not recognized as a supported option.`, modifier); return modifier; } getScheduler(schedulerPolicy, stateTrackingEnabled) { return new EmberScheduler(schedulerPolicy, stateTrackingEnabled); } _setupEmberKVO(proto) { // TODO: Does this make sense in a post-Ember object world? registerOnPrototype(addListener, proto, this._eventNames, this.name, 'perform', false); registerOnPrototype(addListener, proto, this._cancelEventNames, this.name, 'cancelAll', false); registerOnPrototype(addObserver, proto, this._observes, this.name, 'perform', true); } // Provided for compatibility with ember-concurrency TaskProperty extension // methods get taskFn() { return this.taskDefinition; } set taskFn(fn) { this.setTaskDefinition(fn); } } export { TaskFactory }; //# sourceMappingURL=task-factory.js.map