UNPKG

@reactivex/rxjs

Version:

Reactive Extensions for modern JavaScript

135 lines 5.45 kB
"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var root_1 = require('../util/root'); var Subscription_1 = require('../Subscription'); /** * We need this JSDoc comment for affecting ESDoc. * @ignore * @extends {Ignored} */ var FutureAction = (function (_super) { __extends(FutureAction, _super); function FutureAction(scheduler, work) { _super.call(this); this.scheduler = scheduler; this.work = work; this.pending = false; } FutureAction.prototype.execute = function () { if (this.isUnsubscribed) { this.error = new Error('executing a cancelled action'); } else { try { this.work(this.state); } catch (e) { this.unsubscribe(); this.error = e; } } }; FutureAction.prototype.schedule = function (state, delay) { if (delay === void 0) { delay = 0; } if (this.isUnsubscribed) { return this; } return this._schedule(state, delay); }; FutureAction.prototype._schedule = function (state, delay) { var _this = this; if (delay === void 0) { delay = 0; } // Always replace the current state with the new state. this.state = state; // Set the pending flag indicating that this action has been scheduled, or // has recursively rescheduled itself. this.pending = true; var id = this.id; // If this action has an intervalID and the specified delay matches the // delay we used to create the intervalID, don't call `setInterval` again. if (id != null && this.delay === delay) { return this; } this.delay = delay; // If this action has an intervalID, but was rescheduled with a different // `delay` time, cancel the current intervalID and call `setInterval` with // the new `delay` time. if (id != null) { this.id = null; root_1.root.clearInterval(id); } // // Important implementation note: // // By default, FutureAction only executes once. However, Actions have the // ability to be rescheduled from within the scheduled callback (mimicking // recursion for asynchronous methods). This allows us to implement single // and repeated actions with the same code path without adding API surface // area, and implement tail-call optimization over asynchronous boundaries. // // However, JS runtimes make a distinction between intervals scheduled by // repeatedly calling `setTimeout` vs. a single `setInterval` call, with // the latter providing a better guarantee of precision. // // In order to accommodate both single and repeatedly rescheduled actions, // use `setInterval` here for both cases. By default, the interval will be // canceled after its first execution, or if the action schedules itself to // run again with a different `delay` time. // // If the action recursively schedules itself to run again with the same // `delay` time, the interval is not canceled, but allowed to loop again. // The check of whether the interval should be canceled or not is run every // time the interval is executed. The first time an action fails to // reschedule itself, the interval is canceled. // this.id = root_1.root.setInterval(function () { _this.pending = false; var _a = _this, id = _a.id, scheduler = _a.scheduler; scheduler.actions.push(_this); scheduler.flush(); // // Terminate this interval if the action didn't reschedule itself. // Don't call `this.unsubscribe()` here, because the action could be // rescheduled later. For example: // // ``` // scheduler.schedule(function doWork(counter) { // /* ... I'm a busy worker bee ... */ // var originalAction = this; // /* wait 100ms before rescheduling this action again */ // setTimeout(function () { // originalAction.schedule(counter + 1); // }, 100); // }, 1000); // ``` if (_this.pending === false && id != null) { _this.id = null; root_1.root.clearInterval(id); } }, delay); return this; }; FutureAction.prototype._unsubscribe = function () { this.pending = false; var _a = this, id = _a.id, scheduler = _a.scheduler; var actions = scheduler.actions; var index = actions.indexOf(this); if (id != null) { this.id = null; root_1.root.clearInterval(id); } if (index !== -1) { actions.splice(index, 1); } this.work = null; this.state = null; this.scheduler = null; }; return FutureAction; }(Subscription_1.Subscription)); exports.FutureAction = FutureAction; //# sourceMappingURL=FutureAction.js.map