mobx-utils
Version:
Utility functions and common patterns for MobX
85 lines (84 loc) • 2.84 kB
JavaScript
import { _isComputingDerivation } from "mobx";
import { fromResource } from "./from-resource";
var tickers = {};
/**
* Disposes of all the internal Observables created by invocations of `now()`.
*
* The use case for this is to ensure that unit tests can run independent of each other.
* You should not call this in regular application code.
*
* @example
* afterEach(() => {
* utils.resetNowInternalState()
* })
*/
export function resetNowInternalState() {
for (var _i = 0, _a = Object.getOwnPropertyNames(tickers); _i < _a.length; _i++) {
var key = _a[_i];
tickers[key].dispose();
delete tickers[key];
}
}
/**
* Returns the current date time as epoch number.
* The date time is read from an observable which is updated automatically after the given interval.
* So basically it treats time as an observable.
*
* The function takes an interval as parameter, which indicates how often `now()` will return a new value.
* If no interval is given, it will update each second. If "frame" is specified, it will update each time a
* `requestAnimationFrame` is available.
*
* Multiple clocks with the same interval will automatically be synchronized.
*
* Countdown example: https://jsfiddle.net/mweststrate/na0qdmkw/
*
* @example
*
* const start = Date.now()
*
* autorun(() => {
* console.log("Seconds elapsed: ", (mobxUtils.now() - start) / 1000)
* })
*
*
* @export
* @param {(number | "frame")} [interval=1000] interval in milliseconds about how often the interval should update
* @returns
*/
export function now(interval) {
if (interval === void 0) { interval = 1000; }
if (!_isComputingDerivation()) {
// See #40
return Date.now();
}
if (!tickers[interval]) {
if (typeof interval === "number")
tickers[interval] = createIntervalTicker(interval);
else
tickers[interval] = createAnimationFrameTicker();
}
return tickers[interval].current();
}
function createIntervalTicker(interval) {
var subscriptionHandle;
return fromResource(function (sink) {
sink(Date.now());
subscriptionHandle = setInterval(function () { return sink(Date.now()); }, interval);
}, function () {
clearInterval(subscriptionHandle);
}, Date.now());
}
function createAnimationFrameTicker() {
var frameBasedTicker = fromResource(function (sink) {
sink(Date.now());
function scheduleTick() {
window.requestAnimationFrame(function () {
sink(Date.now());
if (frameBasedTicker.isAlive())
scheduleTick();
});
}
scheduleTick();
}, function () { }, Date.now());
return frameBasedTicker;
}