/*! | |
* Copyright 2015 Google Inc. All rights reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
* or implied. See the License for the specific language governing | |
* permissions and limitations under the License. | |
*/ | |
/* | |
* @see https://developers.google.com/web/updates/2015/08/using-requestidlecallback | |
*/ | |
window.requestIdleCallback = window.requestIdleCallback || | |
function (cb) { | |
return setTimeout(function () { | |
var start = Date.now(); | |
cb({ | |
didTimeout: false, | |
timeRemaining: function () { | |
return Math.max(0, 50 - (Date.now() - start)); | |
} | |
}); | |
}, 1); | |
} | |
window.cancelIdleCallback = window.cancelIdleCallback || | |
function (id) { | |
clearTimeout(id); | |
} |
This comment has been minimized.
This comment has been minimized.
Shouldn't |
This comment has been minimized.
This comment has been minimized.
would it be better to try to use |
This comment has been minimized.
This comment has been minimized.
@piuccio I suspect you're right. At least that way there's some kind of deadline to work with. Though, as I think on it, if you call the shim back-to-back you're still going to be inside the same task loop / frame so it's probably as bad. That said, it's definitely closer to spec, so I updated it. @getify possibly, although rAF may well be just as badly timed here as setTimeout. Let's say you do a rIC callback using rAF as the shim. Now you get rAF firing and you maybe run for 50ms (or longer) and you blow the frame budget. This, I guess, is why rIC exists at all. Us devs don't get enough info to make the decision as to the when, so we have to rely on the UA to tell us "now is a good time". Another thought here is that one should avoid DOM mutation in a rIC callback (fragments are a-ok) since DOM manipulation is far less deterministic than other ops, and you can end up forcing a sync layout and so on. Generally there's just no good way to genuinely shim rIC, so while I don't like setTimeout, all the other options are as ick. |
This comment has been minimized.
This comment has been minimized.
@paullewis Would it be possible for the window.requestIdleCallback = window.requestIdleCallback ||
function (cb) {
var start = Date.now(); // ADDED
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return 50 - (Date.now() - start); // ADDED
}
});
}, 1);
} It seems to work relatively well: Note: The first number ( |
This comment has been minimized.
This comment has been minimized.
@simevidas Great idea. Incorporated it, though I made sure it never goes < 0. |
This comment has been minimized.
This comment has been minimized.
Should this be using performance.now() instead of Date.now? :) |
This comment has been minimized.
This comment has been minimized.
@igrigorik Only supported as of iOS 9, which is just a touch too soon for my tastes on a shim. Bit of a shame, really. |
This comment has been minimized.
This comment has been minimized.
As this article says |
This comment has been minimized.
This comment has been minimized.
@getify rAF might still be better if the work to be done in the rIC happens to fit within a frame. Maybe using |
This comment has been minimized.
This comment has been minimized.
@paullewis I stumbled on Basically what I'm looking for is something like What exactly is The |
This comment has been minimized.
This comment has been minimized.
@paullewis Shouldn't window.requestIdleCallback = window.requestIdleCallback ||
function (cb) {
- var start = Date.now();
return setTimeout(function () {
+ var start = Date.now();
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
}
});
}, 1); See also wikimedia/mediawiki@55fc2a9#mediawiki.requestIdleCallback.js. |
This comment has been minimized.
This comment has been minimized.
@Krinkle it your version Basically in original version you can kind of limit idle period https://developers.google.com/web/updates/2015/08/using-requestidlecallback |
This comment has been minimized.
This uses
setTimeout
as its fallback, because in lieu ofrequestIdleCallback
you're most likely to just call your function immediately. Not ideal to redirect calls tosetTimeout
because it's not an API that will pick an idle time (which is whyrequestIdleCallback
exists!).This is a shim rather than an attempt at a polyfill because it's redirecting the call rather than making promises about behavior. Upside is this is Progressive Enhancement-friendly, and you can use this knowing that it will use full-fat👍
requestIdleCallback
when available, and when it's not it will schedule a task, which is no worse than what you would have had to do anyway.