package.src.async.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of component-base Show documentation
Show all versions of component-base Show documentation
Vaadin component base mixins
/**
* @license
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
/**
* @fileoverview
*
* This module provides a number of strategies for enqueuing asynchronous
* tasks. Each sub-module provides a standard `run(fn)` interface that returns a
* handle, and a `cancel(handle)` interface for canceling async tasks before
* they run.
*
* @summary Module that provides a number of strategies for enqueuing
* asynchronous tasks.
*/
let microtaskCurrHandle = 0;
let microtaskLastHandle = 0;
const microtaskCallbacks = [];
let microtaskScheduled = false;
function microtaskFlush() {
microtaskScheduled = false;
const len = microtaskCallbacks.length;
for (let i = 0; i < len; i++) {
const cb = microtaskCallbacks[i];
if (cb) {
try {
cb();
} catch (e) {
setTimeout(() => {
throw e;
});
}
}
}
microtaskCallbacks.splice(0, len);
microtaskLastHandle += len;
}
/**
* Async interface wrapper around `setTimeout`.
*
* @namespace
* @summary Async interface wrapper around `setTimeout`.
*/
const timeOut = {
/**
* Returns a sub-module with the async interface providing the provided
* delay.
*
* @memberof timeOut
* @param {number=} delay Time to wait before calling callbacks in ms
* @return {!AsyncInterface} An async timeout interface
*/
after(delay) {
return {
run(fn) {
return window.setTimeout(fn, delay);
},
cancel(handle) {
window.clearTimeout(handle);
},
};
},
/**
* Enqueues a function called in the next task.
*
* @memberof timeOut
* @param {!Function} fn Callback to run
* @param {number=} delay Delay in milliseconds
* @return {number} Handle used for canceling task
*/
run(fn, delay) {
return window.setTimeout(fn, delay);
},
/**
* Cancels a previously enqueued `timeOut` callback.
*
* @memberof timeOut
* @param {number} handle Handle returned from `run` of callback to cancel
* @return {void}
*/
cancel(handle) {
window.clearTimeout(handle);
},
};
export { timeOut };
/**
* Async interface wrapper around `requestAnimationFrame`.
*
* @namespace
* @summary Async interface wrapper around `requestAnimationFrame`.
*/
const animationFrame = {
/**
* Enqueues a function called at `requestAnimationFrame` timing.
*
* @memberof animationFrame
* @param {function(number):void} fn Callback to run
* @return {number} Handle used for canceling task
*/
run(fn) {
return window.requestAnimationFrame(fn);
},
/**
* Cancels a previously enqueued `animationFrame` callback.
*
* @memberof animationFrame
* @param {number} handle Handle returned from `run` of callback to cancel
* @return {void}
*/
cancel(handle) {
window.cancelAnimationFrame(handle);
},
};
export { animationFrame };
/**
* Async interface wrapper around `requestIdleCallback`. Falls back to
* `setTimeout` on browsers that do not support `requestIdleCallback`.
*
* @namespace
* @summary Async interface wrapper around `requestIdleCallback`.
*/
const idlePeriod = {
/**
* Enqueues a function called at `requestIdleCallback` timing.
*
* @memberof idlePeriod
* @param {function(!IdleDeadline):void} fn Callback to run
* @return {number} Handle used for canceling task
*/
run(fn) {
return window.requestIdleCallback ? window.requestIdleCallback(fn) : window.setTimeout(fn, 16);
},
/**
* Cancels a previously enqueued `idlePeriod` callback.
*
* @memberof idlePeriod
* @param {number} handle Handle returned from `run` of callback to cancel
* @return {void}
*/
cancel(handle) {
if (window.cancelIdleCallback) {
window.cancelIdleCallback(handle);
} else {
window.clearTimeout(handle);
}
},
};
export { idlePeriod };
/**
* Async interface for enqueuing callbacks that run at microtask timing.
*
* @namespace
* @summary Async interface for enqueuing callbacks that run at microtask
* timing.
*/
const microTask = {
/**
* Enqueues a function called at microtask timing.
*
* @memberof microTask
* @param {!Function=} callback Callback to run
* @return {number} Handle used for canceling task
*/
run(callback) {
if (!microtaskScheduled) {
microtaskScheduled = true;
queueMicrotask(() => microtaskFlush());
}
microtaskCallbacks.push(callback);
const result = microtaskCurrHandle;
microtaskCurrHandle += 1;
return result;
},
/**
* Cancels a previously enqueued `microTask` callback.
*
* @memberof microTask
* @param {number} handle Handle returned from `run` of callback to cancel
* @return {void}
*/
cancel(handle) {
const idx = handle - microtaskLastHandle;
if (idx >= 0) {
if (!microtaskCallbacks[idx]) {
throw new Error(`invalid async handle: ${handle}`);
}
microtaskCallbacks[idx] = null;
}
},
};
export { microTask };