UNPKG

@enact/core

Version:

Enact is an open source JavaScript framework containing everything you need to create a fast, scalable mobile or web application.

276 lines (275 loc) 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.Job = void 0; var _invariant = _interopRequireDefault(require("invariant")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * Provides a convenient way to manage timed execution of functions. * * @class Job * @memberof core/util * @public */ var Job = exports.Job = /*#__PURE__*/function () { /** * @constructor * @param {Function} fn Function to execute as the requested job. * @param {Number} timeout The number of milliseconds to wait before starting the job. * * @memberof core/util.Job.prototype */ function Job(fn, _timeout) { var _this = this; _classCallCheck(this, Job); this.id = null; this.fn = null; this.timeout = null; this.type = null; /** * Starts the job. * * @method * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.start = function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this.startAfter.apply(_this, [_this.timeout].concat(args)); }; /** * Starts the job in `timeout` milliseconds * * @method * @param {Number} timeout The number of milliseconds to wait before starting the job. * This supersedes the timeout set at construction. * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.startAfter = function (timeout) { for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } _this.stop(); _this.type = 'timeout'; _this.id = setTimeout(function () { return _this.run(args); }, timeout); }; /** * Stops the job. * * @method * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.stop = function () { if (_this.id) { if (_this.type === 'idle') { window.cancelIdleCallback(_this.id); } else if (_this.type === 'raf') { window.cancelAnimationFrame(_this.id); } else if (_this.type === 'timeout') { clearTimeout(_this.id); } _this.id = _this.type = null; } }; /** * Executes the job immediately, then prevents any other calls to `throttle()` from running * until the `timeout` configured at construction passes. * * @method * @param {...*} args Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.throttle = function () { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } _this.throttleUntil.apply(_this, [_this.timeout].concat(args)); }; /** * Executes the job immediately, then prevents any other calls to `throttle()` from running for * `timeout` milliseconds. * * @method * @param {Number} timeout The number of milliseconds to wait before allowing the job to * be ran again. This supersedes the timeout set at construction. * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.throttleUntil = function (timeout) { if (!_this.id) { _this.type = 'timeout'; for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { args[_key4 - 1] = arguments[_key4]; } _this.run(args); _this.id = setTimeout(_this.stop, timeout); } }; /** * Executes job when the CPU is idle. * * @method * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.idle = function () { for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } _this.idleUntil.apply(_this, [null].concat(args)); }; /** * Executes job when the CPU is idle, or when the timeout is reached, whichever occurs first. * * @method * @param {Number} timeout The number of milliseconds to wait before executing the * job. This guarantees that the job is run, if a positive value * is specified. * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.idleUntil = function (timeout) { for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { args[_key6 - 1] = arguments[_key6]; } if (typeof window !== 'undefined' && window.requestIdleCallback) { _this.stop(); _this.type = 'idle'; _this.id = window.requestIdleCallback(function () { return _this.run(args); }, { timeout: timeout }); } else { // since we can't request an idle callback, just pass to startAfter() _this.startAfter.apply(_this, [timeout].concat(args)); } }; /** * Executes job before the next repaint. * * @method * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.startRaf = function () { for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } _this.startRafAfter.apply(_this, [_this.timeout].concat(args)); }; /** * Executes job before the next repaint after a given amount of timeout. * * @method * @param {Number} timeout The number of milliseconds to wait before running `requestAnimationFrame`. * @param {...*} [args] Any args passed are forwarded to the callback * * @returns {undefined} * @memberof core/util.Job.prototype * @public */ this.startRafAfter = function (timeout) { for (var _len8 = arguments.length, args = new Array(_len8 > 1 ? _len8 - 1 : 0), _key8 = 1; _key8 < _len8; _key8++) { args[_key8 - 1] = arguments[_key8]; } _this.type = 'raf'; if (typeof window !== 'undefined') { var time = null; var _callback = function callback(timestamp) { if (time === null) { time = timestamp; } if (timeout && timestamp - time < timeout) { _this.id = window.requestAnimationFrame(_callback); } else { time = null; _this.run(args); window.cancelAnimationFrame(_this.id); _this.id = null; } }; _this.id = window.requestAnimationFrame(_callback); } else { // If requestAnimationFrame is not supported just run the function immediately _this.run(args); } }; /** * Starts the job when `promise` resolves. * * The job execution is tied to the resolution of the last `Promise` passed. Like other methods * on `Job`, calling `promise()` again with a new `Promise` will block execution of the job * until that new `Promise` resolves. Any previous `Promise`s will still resolve normally but * will not trigger job execution. * * Unlike other methods on `Job`, `promise()` returns a `Promise` which is the result of calling * `then()` on the passed `promise`. That `Promise` resolves with either the result of job * execution or `undefined` if `Promise` was superseded by a subsequent `Promise` passed as * described above. * * @method * @param {Promise} promise The promise that must resolve before the job is executed * * @returns {Promise} * @memberof core/util.Job.prototype * @public */ this.promise = function (promise) { !(promise && typeof promise.then === 'function') ? process.env.NODE_ENV !== "production" ? (0, _invariant["default"])(false, 'promise expects a thenable') : (0, _invariant["default"])(false) : void 0; _this.type = 'promise'; _this.id = promise; return promise.then(function (result) { if (_this.id === promise) { _this.stop(); return _this.run([result]); } }); }; this.fn = fn; this.timeout = _timeout; } return _createClass(Job, [{ key: "run", value: function run(args) { // don't want to inadvertently apply Job's context on `fn` return this.fn.apply(null, args); } }]); }(); var _default = exports["default"] = Job;