I created a function using requestAnimationFrame
loop that works pretty much like the plain JS setTimeout
function (except that a custom starting time can be optionally given for the duration, and it returns the finish time). I wonder whether this is an ideal way of writing it. In particular, I had some issues with self-references while defining the main object, so I had to define them separately. (Maybe it would make more sense to create a class, but I'd like to keep it as simple as possible.)
const DT = {
// initiate RTOloop ("setTimeout" via RAF loop)
// actually defined below, because of self-reference
setRTO: undefined,
// RTOloop actually defined below, because of self-reference
RTOloop: undefined,
// start time for setRTOLoop
RTOstart: undefined,
// duration for setRTOLoop
RTOduration: undefined,
// callback function for setRTOLoop
RTOcallback: undefined,
// now: gets the appropriate version of "performance.now()"
// normally available in all modern browsers, but it can resort to the still precise Date()
// see https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
now: function() {
let performance = window.performance || {};
performance.now = (function() {
return (
performance.now ||
performance.webkitNow ||
performance.msNow ||
performance.oNow ||
performance.mozNow ||
function() {
return new Date().getTime();
}
);
})();
return performance.now();
}
};
// add the RAF Time-Out (RTO) initiation function definition
DT.setRTO = function(callback, duration, start = DT.now()) {
DT.RTOstart = start;
DT.RTOduration = duration;
DT.RTOcallback = callback;
DT.RTOloop(start);
};
// add the RAF setRTO function definition
DT.RTOloop = function(timestamp) {
if (timestamp - DT.RTOstart < DT.RTOduration) {
requestAnimationFrame((RAFtimestamp) => DT.RTOloop(RAFtimestamp));
} else {
DT.RTOcallback(timestamp, DT.RTOstart);
DT.RTOcallback = undefined;
DT.RTOstart = undefined;
DT.RTOduration = undefined;
}
};
Object.seal(DT);
// example use
DT.setRTO((stamp, start) => console.log(stamp - start), 500);
(Edit: This function is intended to be called from within an initial RAF callback, hence the timing is expected to be in sync with repaints.)