requestIdleCallback 示例
通过具体例子,来理解浏览器性能优化相关的api,即requestIdleCallback.
https://www.cnblogs.com/galenyip/p/4856996.html
https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API#example
*requrestAnimationFrame 相关文章
示例一
/**
* 原文网站
* https://www.cnblogs.com/galenyip/p/4856996.html
*/
var eventsToSend = [];
var isRequestIdleCallbackScheduled = false;
function onNavOpenClick() {
// animate the menu
document.body.classList.add('open');
eventsToSend.push({
category: 'button',
action: 'click',
label: 'nav',
value: 'open'
});
schedulePendingEvents();
}
function schedulePendingEvents() {
if (isRequestIdleCallbackScheduled)
return;
isRequestIdleCallbackScheduled = true;
if ('requestIdleCallback' in window) {
requestIdleCallback(processPendingAnalyticsEvents, { timeout: 2000 });
} else {
processPendingAnalyticsEvents();
}
}
function processPendingAnalyticsEvents(deadline) {
isRequestIdleCallbackScheduled = false;
if (typeof deadline === 'undefined') {
deadline = { timeRemaining: function() { return Number.MAX_VALUE } };
}
while (deadline.timeRemaining() > 0 && eventsToSend.length > 0) {
var evt = eventsToSend.pop();
// 耗时操作
console.log(evt);
}
if (eventsToSend.length > 0) {
schedulePendingEvents();
}
}
示例二
/**
* 原文网站
* https://www.cnblogs.com/galenyip/p/4856996.html
*/
var elementsToAdd = [];
var documentFragment;
var isVisualUpdateScheduled = false;
function onAddButtonClick() {
elementsToAdd.push({
tag: 'div',
content: new Date().getTime()
});
scheduleElementCreation();
}
function scheduleElementCreation() {
if ('requestIdleCallback' in window) {
requestIdleCallback(processPendingElements, { timeout: 2000 });
} else {
processPendingElements();
}
}
function processPendingElements(deadline) {
if (typeof deadline === 'undefined') {
deadline = { timeRemaining: function() { return Number.MAX_VALUE } };
}
if (!documentFragment) {
documentFragment = document.createDocumentFragment();
}
while (deadline.timeRemaining() > 0 && elementsToAdd.length > 0) {
var elToAdd = elementsToAdd.pop();
var el = document.createElement(elToAdd.tag);
el.textContent = elToAdd.content;
documentFragment.appendChild(el);
// Don't append to the document immediately, wait for the next
// requestAnimationFrame callback.
scheduleVisualUpdateIfNeeded();
}
if (elementsToAdd.length > 0) {
scheduleElementCreation();
}
}
function scheduleVisualUpdateIfNeeded() {
if (isVisualUpdateScheduled)
return;
isVisualUpdateScheduled = true;
requestAnimationFrame(appendDocumentFragment);
}
function appendDocumentFragment() {
isVisualUpdateScheduled = false;
// Append the fragment and reset.
document.body.appendChild(documentFragment);
documentFragment = null;
}
示例三
// https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API#example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
body {
padding: 0;
margin: 0;
}
svg:not(:root) {
display: block;
}
.playable-code {
background-color: #f4f7f8;
border: none;
border-left: 6px solid #558abb;
border-width: medium medium medium 6px;
color: #4d4e53;
height: 100px;
width: 90%;
padding: 10px 10px 0;
}
.playable-canvas {
border: 1px solid #4d4e53;
border-radius: 2px;
}
.playable-buttons {
text-align: right;
width: 90%;
padding: 5px 10px 5px 26px;
}
</style>
<style type="text/css">
body {
font-family: "Open Sans", "Lucida Grande", "Arial", sans-serif;
font-size: 16px;
}
.logBox {
margin-top: 16px;
width: 400px;
height: 500px;
border-radius: 6px;
border: 1px solid black;
box-shadow: 4px 4px 2px black;
}
.logHeader {
margin: 0;
padding: 0 6px 4px;
height: 22px;
background-color: lightblue;
border-bottom: 1px solid black;
border-radius: 6px 6px 0 0;
}
#log {
font: 12px "Courier", monospace;
padding: 6px;
overflow: auto;
overflow-y: scroll;
width: 388px;
height: 460px;
}
.container {
width: 400px;
padding: 6px;
border-radius: 6px;
border: 1px solid black;
box-shadow: 4px 4px 2px black;
display: block;
overflow: auto;
}
.label {
display: inline-block;
}
.counter {
text-align: right;
padding-top: 4px;
float: right;
}
.button {
padding-top: 2px;
padding-bottom: 4px;
width: 100px;
display: inline-block;
float: left;
border: 1px solid black;
cursor: pointer;
text-align: center;
margin-top: 0;
color: white;
background-color: darkgreen;
}
@keyframes slide {
0% {
margin-left: 0;
/* transform: translateX(0); */
}
50% {
margin-left: 200px;
/* transform: translateX(200px); */
}
100% {
margin-left: 0;
/* transform: translateX(0); */
}
}
p {
animation-duration: 3s;
animation-name: slide;
animation-iteration-count: infinite;
}
#progress {
width: 100%;
padding-top: 6px;
}
</style>
<title>Background Tasks API - Example - code sample</title>
</head>
<body>
<p>
Demonstration
</p>
<div class="container">
<div class="label">Decoding quantum filament tachyon emissions...</div>
<progress id="progress" value="0"></progress>
<div class="button" id="startButton">
Start
</div>
<div class="label counter">
Task <span id="currentTaskNumber">0</span> of <span id="totalTaskCount">0</span>
</div>
</div>
<div class="logBox">
<div class="logHeader">
Log
</div>
<div id="log">
</div>
</div>
<script>
let taskList = [];
let totalTaskCount = 0;
let currentTaskNumber = 0;
let taskHandle = null;
let totalTaskCountElem = document.getElementById("totalTaskCount");
let currentTaskNumberElem = document.getElementById("currentTaskNumber");
let progressBarElem = document.getElementById("progress");
let startButtonElem = document.getElementById("startButton");
let logElem = document.getElementById("log");
let logFragment = null;
let statusRefreshScheduled = false;
window.requestIdleCallback = window.requestIdleCallback || function (handler) {
let startTime = Date.now();
return setTimeout(function () {
handler({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50.0 - (Date.now() - startTime));
}
});
}, 1);
};
window.cancelIdleCallback = window.cancelIdleCallback || function (id) {
clearTimeout(id);
};
function enqueueTask(taskHandler, taskData) {
taskList.push({
handler: taskHandler,
data: taskData
});
totalTaskCount++;
if (!taskHandle) {
taskHandle = requestIdleCallback(runTaskQueue, { timeout: 1000 });
}
scheduleStatusRefresh();
}
function runTaskQueue(deadline) {
while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && taskList.length) {
let task = taskList.shift();
console.log(taskList.length)
console.log(deadline.didTimeout)
currentTaskNumber++;
task.handler(task.data);
scheduleStatusRefresh();
}
if (taskList.length) {
taskHandle = requestIdleCallback(runTaskQueue, { timeout: 1000 });
} else {
taskHandle = 0;
}
}
function scheduleStatusRefresh() {
if (!statusRefreshScheduled) {
requestAnimationFrame(updateDisplay);
statusRefreshScheduled = true;
}
}
function updateDisplay() {
let scrolledToEnd = logElem.scrollHeight - logElem.clientHeight <= logElem.scrollTop + 1;
let m = getRandomIntInclusive(1, 10);
document.querySelector('p').textContent = m;
if (totalTaskCount) {
if (progressBarElem.max != totalTaskCount) {
totalTaskCountElem.textContent = totalTaskCount;
progressBarElem.max = totalTaskCount;
}
if (progressBarElem.value != currentTaskNumber) {
currentTaskNumberElem.textContent = currentTaskNumber;
progressBarElem.value = currentTaskNumber;
}
}
if (logFragment) {
logElem.appendChild(logFragment);
logFragment = null;
}
if (scrolledToEnd) {
logElem.scrollTop = logElem.scrollHeight - logElem.clientHeight;
}
statusRefreshScheduled = false;
}
function log(text) {
if (!logFragment) {
logFragment = document.createDocumentFragment();
}
const el = document.createElement("div");
el.textContent = text;
logFragment.appendChild(el);
}
function logTaskHandler(data) {
log("<strong>Running task #" + currentTaskNumber + "</strong>");
for (i = 0; i < data.count; i += 1) {
log((i + 1).toString() + ". " + data.text);
}
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function decodeTechnoStuff() {
totalTaskCount = 0;
currentTaskNumber = 0;
updateDisplay();
let n = getRandomIntInclusive(1, 10);
for (i = 0; i < n; i++) {
let taskData = {
count: getRandomIntInclusive(75, 150),
text: "This text is from task number " + (i + 1).toString() + " of " + n
};
enqueueTask(logTaskHandler, taskData);
}
}
document.getElementById("startButton").addEventListener("click", decodeTechnoStuff, false);
</script>
</body>
</html>
至此,结束。