UNPKG

ember-concurrency

Version:

Improved concurrency/async primitives for Ember.js

264 lines (246 loc) 7.92 kB
import { BaseTaskInstance } from './external/task-instance/base.js'; import { TRACKED_INITIAL_INSTANCE_STATE } from './tracked-state.js'; /** A `TaskInstance` represent a single execution of a {@linkcode Task}. Every call to {@linkcode Task#perform} returns a `TaskInstance`. `TaskInstance`s are cancelable, either explicitly via {@linkcode TaskInstance#cancel} or {@linkcode Task#cancelAll}, or automatically due to the host object being destroyed, or because concurrency policy enforced by a {@linkcode TaskProperty Task Modifier} canceled the task instance. <style> .ignore-this--this-is-here-to-hide-constructor, #TaskInstance { display: none } </style> @class TaskInstance */ class TaskInstance extends BaseTaskInstance { setState(props) { let state = this._recomputeState(props); Object.assign(this, { ...props, isRunning: !props.isFinished, isDropped: state === 'dropped', state }); } _recomputeState(props) { if (props.isDropped) { return 'dropped'; } else if (props.isCanceled) { if (props.hasStarted) { return 'canceled'; } else { return 'dropped'; } } else if (props.isFinished) { return 'finished'; } else if (props.hasStarted) { return 'running'; } else { return 'waiting'; } } onStarted() { this.triggerEvent('started', this); } onSuccess() { this.triggerEvent('succeeded', this); } onError(error) { this.triggerEvent('errored', this, error); } onCancel(cancelReason) { this.triggerEvent('canceled', this, cancelReason); } formatCancelReason(reason) { return `TaskInstance '${this.getName()}' was canceled because ${reason}. For more information, see: http://ember-concurrency.com/docs/task-cancelation-help`; } getName() { if (!this.name) { this.name = this.task && this.task.name || '<unknown>'; } return this.name; } selfCancelLoopWarning(parent) { let parentName = `\`${parent.getName()}\``; let childName = `\`${this.getName()}\``; // eslint-disable-next-line no-console console.warn(`ember-concurrency detected a potentially hazardous "self-cancel loop" between parent task ${parentName} and child task ${childName}. If you want child task ${childName} to be canceled when parent task ${parentName} is canceled, please change \`.perform()\` to \`.linked().perform()\`. If you want child task ${childName} to keep running after parent task ${parentName} is canceled, change it to \`.unlinked().perform()\``); } triggerEvent(...allArgs) { if (!this.hasEnabledEvents) { return; } let taskInstance = this; let task = taskInstance.task; let host = task.context; let eventNamespace = task && task.name; if (host && host.trigger && eventNamespace) { let [eventType, ...args] = allArgs; host.trigger(`${eventNamespace}:${eventType}`, ...args); } } /** * Describes the state that the task instance is in. Can be used for debugging, * or potentially driving some UI state. Possible values are: * * - `"dropped"`: task instance was canceled before it started * - `"canceled"`: task instance was canceled before it could finish * - `"finished"`: task instance ran to completion (even if an exception was thrown) * - `"running"`: task instance is currently running (returns true even if * is paused on a yielded promise) * - `"waiting"`: task instance hasn't begun running yet (usually * because the task is using the {@linkcode TaskProperty#enqueue enqueue} * task modifier) * * The animated timeline examples on the [Task Concurrency](/docs/task-concurrency) * docs page make use of this property. * * @name state * @memberof TaskInstance * @instance * @readOnly */ /** * True if the TaskInstance was canceled before it could * ever start running. For example, calling * {@linkcode Task#perform .perform()} twice on a * task with the {@linkcode TaskProperty#drop drop} modifier applied * will result in the second task instance being dropped. * * @name isDropped * @memberof TaskInstance * @instance * @readOnly */ /** * True if the task is still running. * * @name isRunning * @memberof TaskInstance * @instance * @readOnly */ /** * Event emitted when a new {@linkcode TaskInstance} starts executing. * * `on` from `@ember/object/evented` may be used to create a binding on the host object to the event. * * ```js * export default Component.extend({ * doSomething: task(function * () { * // ... does something * }), * * onDoSomethingStarted: on('doSomething:started', function (taskInstance) { * // ... * }) * }); * ``` * * @event TaskInstance#TASK_NAME:started * @param {TaskInstance} taskInstance - Task instance that was started */ /** * Event emitted when a {@linkcode TaskInstance} succeeds. * * `on` from `@ember/object/evented` may be used to create a binding on the host object to the event. * * ```js * export default Component.extend({ * doSomething: task(function * () { * // ... does something * }), * * onDoSomethingSucceeded: on('doSomething:succeeded', function (taskInstance) { * // ... * }) * }); * ``` * * @event TaskInstance#TASK_NAME:succeeded * @param {TaskInstance} taskInstance - Task instance that was succeeded */ /** * Event emitted when a {@linkcode TaskInstance} throws an an error that is * not handled within the task itself. * * `on` from `@ember/object/evented` may be used to create a binding on the host object to the event. * * ```js * export default Component.extend({ * doSomething: task(function * () { * // ... does something * }), * * onDoSomethingErrored: on('doSomething:errored', function (taskInstance, error) { * // ... * }) * }); * ``` * * @event TaskInstance#TASK_NAME:errored * @param {TaskInstance} taskInstance - Task instance that was started * @param {Error} error - Error that was thrown by the task instance */ /** * Event emitted when a {@linkcode TaskInstance} is canceled. * * `on` from `@ember/object/evented` may be used to create a binding on the host object to the event. * * ```js * export default Component.extend({ * doSomething: task(function * () { * // ... does something * }), * * onDoSomethingCanceled: on('doSomething:canceled', function (taskInstance, cancelationReason) { * // ... * }) * }); * ``` * * @event TaskInstance#TASK_NAME:canceled * @param {TaskInstance} taskInstance - Task instance that was started * @param {string} cancelationReason - Cancelation reason that was was provided to {@linkcode TaskInstance#cancel} */ /** * Cancels the task instance. Has no effect if the task instance has * already been canceled or has already finished running. * * @method cancel * @memberof TaskInstance * @instance * @async */ /** * Returns a promise that resolves with the value returned * from the task's (generator) function, or rejects with * either the exception thrown from the task function, or * an error with a `.name` property with value `"TaskCancelation"`. * * @method then * @memberof TaskInstance * @instance * @return {Promise} */ /** * @method catch * @memberof TaskInstance * @instance * @return {Promise} */ /** * @method finally * @memberof TaskInstance * @instance * @return {Promise} */ } if (TRACKED_INITIAL_INSTANCE_STATE) { Object.defineProperties(TaskInstance.prototype, TRACKED_INITIAL_INSTANCE_STATE); } export { TaskInstance }; //# sourceMappingURL=task-instance.js.map