@reactivex/rxjs
Version:
Reactive Extensions for modern JavaScript
135 lines • 6 kB
JavaScript
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 __());
};
define(["require", "exports", '../util/root', '../Subscription'], function (require, exports, root_1, Subscription_1) {
"use strict";
/**
* 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