No setTimeout, No setInterval
Èç¹ûÄã²»µÃ²»Ê¹ÓÃsetTimeout»òÕßsetIntervalÀ´ÊµÏÖ¶¯»£¬ÄÇôÔÒòÖ»ÄÜÊÇÄãÐèÒª¾«È·µÄ¿ØÖƶ¯»¡£µ«ÎÒÈÏΪÖÁÉÙÔÚÏÖÔÚÕâ¸öʱ¼äµã£¬¸ß¼¶ä¯ÀÀÆ÷¡¢ÉõÖÁÊÖ»úä¯ÀÀÆ÷µÄÆÕ¼°³Ì¶È×ã¹»ÈÃÄãÓÐÀíÓÉÓÐÌõ¼þÔÚʵÏÖ¶¯»Ê±Ê¹Óøü¸ßЧµÄ·½Ê½¡£
ʲôÊǸßЧ
Ò³ÃæÊÇÿһ֡±ä»¯¶¼ÊÇϵͳ»æÖƳöÀ´µÄ(GPU»òÕßCPU)¡£µ«ÕâÖÖ»æÖÆÓÖºÍPCÓÎÏ·µÄ»æÖƲ»Í¬£¬ËüµÄ×î¸ß»æÖÆÆµÂÊÊÜÏÞÓÚÏÔʾÆ÷µÄË¢ÐÂÆµÂÊ(¶ø·ÇÏÔ¿¨)£¬ËùÒÔ´ó¶àÊýÇé¿öÏÂ×î¸ßµÄ»æÖÆÆµÂÊÖ»ÄÜÊÇÿÃë60Ö¡(frame
per second£¬ÒÔÏÂÓÃfps¼ò³Æ)£¬¶ÔÓ¦ÓÚÏÔʾÆ÷µÄ60Hz¡£60fpsÊÇÒ»¸ö×îÀíÏëµÄ״̬£¬ÔÚÈÕ³£¶ÔÒ³ÃæÐÔÄܵIJâÊÔÖУ¬60fpsÒ²ÊÇÒ»¸öÖØÒªµÄÖ¸±ê£¬the
closer the better¡£ÔÚChromeµÄµ÷ÊÔ¹¤¾ßÖУ¬Óв»ÉÙ¹¤¾ß¶¼ÊÇÓÃÓÚºâÁ¿µ±Ç°Ö¡Êý£º

½ÓÏÂÀ´µÄ¹¤×÷ÖУ¬ÎÒÃǽ«»áÓõ½ÕâЩ¹¤¾ß£¬À´ÊµÊ±²é¿´ÎÒÃÇÒ³ÃæµÄÐÔÄÜ¡£
60fpsÊǶ¯Á¦Ò²ÊÇѹÁ¦£¬ÒòΪËüÒâζ×ÅÎÒÃÇÖ»ÓÐ16.7ºÁÃë(1000 / 60)À´»æÖÆÃ¿Ò»Ö¡¡£Èç¹ûʹÓÃsetTimeout»òÕßsetInterval(ÒÔÏÂͳ³ÆÎªtimer)À´¿ØÖÆ»æÖÆ£¬ÎÊÌâ¾ÍÀ´ÁË¡£
Ê×ÏÈ£¬Timer¼ÆËãÑÓʱµÄ¾«È·¶È²»¹»¡£ÑÓʱµÄ¼ÆËãÒÀ¿¿µÄÊÇä¯ÀÀÆ÷µÄÄÚÖÃʱÖÓ£¬¶øÊ±Öӵľ«È·¶ÈÓÖÈ¡¾öÓÚʱÖÓ¸üÐÂµÄÆµÂÊ(Timer
resolution)¡£IE8¼°Æä֮ǰµÄIE°æ±¾¸üмä¸ôΪ15.6ºÁÃë¡£¼ÙÉèÄãÉ趨µÄsetTimeoutÑÓ³ÙΪ16.7ms£¬ÄÇôËüÒª¸üÐÂÁ½¸ö15.6ºÁÃë²Å»á¸Ã´¥·¢ÑÓʱ¡£ÕâÒ²Òâζ×ÅÎÞ¹ÊÑÓ³ÙÁË
15.6 x 2 - 16.7 = 14.5ºÁÃë¡£
16.7ms DELAY: |------------|
CLOCK: |----------|----------|
15.6ms 15.6ms |
ËùÒÔ¼´Ê¹Äã¸øsetTimeoutÉ趨µÄÑÓʱΪ0ms£¬ËüÒ²²»»áÁ¢¼´´¥·¢¡£Ä¿Ç°ChromeÓëIE9+ä¯ÀÀÆ÷µÄ¸üÐÂÆµÂʶ¼Îª4ms(Èç¹ûÄãʹÓõÄÊDZʼDZ¾µçÄÔ£¬²¢ÇÒÔÚʹÓÃµç³Ø¶ø·ÇµçÔ´µÄģʽÏ£¬ÎªÁ˽ÚÊ¡×ÊÔ´£¬ä¯ÀÀÆ÷»á½«¸üÐÂÆµÂÊÇл»ÖÁÓÚϵͳʱ¼äÏàͬ£¬Ò²¾ÍÒâζןüÐÂÆµÂʸüµÍ)¡£
ÍËÒ»²½Ëµ£¬¼Ùʹtimer resolutionÄܹ»´ïµ½16.7ms£¬Ëü»¹ÒªÃæÁÙÒ»¸öÒì²½¶ÓÁеÄÎÊÌâ¡£ÒòΪÒì²½µÄ¹ØÏµsetTimeoutÖеĻص÷º¯Êý²¢·ÇÁ¢¼´Ö´ÐУ¬¶øÊÇÐèÒª¼ÓÈëµÈ´ý¶ÓÁÐÖС£µ«ÎÊÌâÊÇ£¬Èç¹ûÔڵȴýÑÓ³Ù´¥·¢µÄ¹ý³ÌÖУ¬ÓÐеÄͬ²½½Å±¾ÐèÒªÖ´ÐУ¬ÄÇôͬ²½½Å±¾²»»áÅÅÔÚtimerµÄ»Øµ÷Ö®ºó£¬¶øÊÇÁ¢¼´Ö´ÐУ¬±ÈÈçÏÂÃæÕâ¶Î´úÂ룺
function runForSeconds(s) { var start = +new Date(); while (start + s * 1000 > (+new Date())) {} }
document.body.addEventListener("click",
function () {
runForSeconds(10);
}, false);
setTimeout(function () {
console.log("Done!");
}, 1000 * 3); |
Èç¹ûÔڵȴý´¥·¢ÑÓ³ÙµÄ3Ãë¹ý³ÌÖУ¬ÓÐÈ˵ã»÷ÁËbody£¬ÄÇô»Øµ÷»¹ÊÇ׼ʱÔÚ3sÍê³Éʱ´¥·¢Â𣿵±È»²»ÄÜ£¬Ëü»áµÈ´ý10s£¬Í¬²½º¯Êý×ÜÊÇÓÅÏÈÓÚÒì²½º¯Êý£º
µÈ´ý3ÃëÑÓ³Ù | 1s | 2s | 3s |--->console.log("Done!");
¾¹ý2Ãë |----1s----|----2s----| |--->console.log("Done!");
µã»÷bodyºó
ÒÔΪÊÇÕâÑù£º|----1s----|----2s----|----3s----|--->console.log("Done!")--->|------------------10s----------------|
ÆäʵÊÇÕâÑù£º|----1s----|----2s----|------------------10s----------------|--->console.log("Done!"); |
John ResignÓÐÈýƪ¹ØÓÚTimerÐÔÄÜÓë׼ȷÐÔµÄÎÄÕÂ: 1.Accuracy of JavaScript
Time, 2.Analyzing Timer Performance£¬ 3.How JavaScript
Timers Work¡£´ÓÎÄÕÂÖпÉÒÔ¿´µ½TimerÔÚ²»Í¬Æ½Ì¨ä¯ÀÀÆ÷Óë²Ù×÷ϵͳϵÄһЩÎÊÌâ¡£
ÔÙÍËÒ»²½Ëµ£¬¼ÙÉètimer resolutionÄܹ»´ïµ½16.7ms£¬²¢ÇÒ¼ÙÉèÒì²½º¯Êý²»»á±»ÑÓºó£¬Ê¹ÓÃtimer¿ØÖƵ͝»»¹ÊÇÓв»¾¡ÈçÈËÒâµÄµØ·½¡£ÕâÒ²¾ÍÊÇÏÂÒ»½ÚҪ˵µÄÎÊÌâ¡£
´¹Ö±Í¬²½ÎÊÌâ
ÕâÀïÇëÔÙÔÊÐíÎÒÒýÈëÁíÒ»¸ö³£Á¿60¡ª¡ªÆÁÄ»µÄË¢ÐÂÂÊ60Hz¡£
60HzºÍ60fpsÓÐʲô¹ØÏµ£¿Ã»ÓÐÈκιØÏµ¡£fps´ú±íGPUäÖȾ»ÃæµÄƵÂÊ£¬Hz´ú±íÏÔʾÆ÷Ë¢ÐÂÆÁÄ»µÄƵÂÊ¡£Ò»·ù¾²Ì¬Í¼Æ¬£¬Äã¿ÉÒÔ˵Õ⸱ͼƬµÄfpsÊÇ0Ö¡/Ã룬µ«¾ø¶Ô²»ÄÜ˵´ËʱÆÁÄ»µÄË¢ÐÂÂÊÊÇ0Hz£¬Ò²¾ÍÊÇ˵ˢÐÂÂʲ»ËæÍ¼ÏñÄÚÈݵı仯¶ø±ä»¯¡£ÓÎÏ·Ò²ºÃä¯ÀÀÆ÷Ò²ºÃ£¬ÎÒÃÇ̸µ½µôÖ¡£¬ÊÇÖ¸GPUäÖȾ»ÃæÆµÂʽµµÍ¡£±ÈÈçµøÂäµ½30fpsÉõÖÁ20fps£¬µ«ÒòΪÊÓ¾õÔÝÁôÔÀí£¬ÎÒÃÇ¿´µ½µÄ»ÃæÈÔÈ»ÊÇÔ˶¯ºÍÁ¬¹áµÄ¡£
½ÓÉÏÒ»½Ú£¬ÎÒÃǼÙÉèÿһ´Îtimer¶¼²»»áÓÐÑÓʱ£¬Ò²²»»á±»Í¬²½º¯Êý¸ÉÈÅ£¬ÉõÖÁÄܰÑʱ¼äËõ¶ÌÖÁ16ms£¬ÄÇô»á·¢ÉúÊ²Ã´ÄØ£º
ÔÚ22Ãë´¦·¢ÉúÁ˶ªÖ¡
Èç¹û°ÑÑÓ³Ùʱ¼äËõµÄ¸ü¶Ì£¬¶ªÊ§µÄÖ¡ÊýÒ²¾Í¸ü¶à£º

ʵ¼ÊÇé¿ö»á±ÈÒÔÉÏÏëÏóµÄ¸´ÔӵĶࡣ¼´Ê¹ÄãÄܸø³öÒ»¸ö¹Ì¶¨µÄÑÓʱ£¬½â¾ö60HzÆÁĻ϶ªÖ¡ÎÊÌ⣬ÄÇôÆäËûË¢ÐÂÆµÂʵÄÏÔʾÆ÷Ó¦¸ÃÔõô°ì£¬ÒªÖªµÀ²»Í¬É豸¡¢ÉõÖÁÏàͬÉ豸ÔÚ²»Í¬µç³Ø×´Ì¬ÏÂµÄÆÁĻˢÐÂÂʶ¼²»¾¡Ïàͬ¡£
ÒÔÉÏͬʱ»¹ºöÂÔÁËÆÁĻˢÐÂ»ÃæµÄʱ¼ä³É±¾¡£ÎÊÌâ²úÉúÓÚGPUäÖȾ»ÃæµÄƵÂÊºÍÆÁĻˢÐÂÆµÂʵIJ»Ò»Ö£ºÈç¹ûGPUäÖȾ³öÒ»Ö¡»ÃæµÄʱ¼ä±ÈÏÔʾÆ÷Ë¢ÐÂÒ»ÕÅ»ÃæµÄʱ¼äÒª¶Ì(¸ü¿ì)£¬ÄÇôµ±ÏÔʾÆ÷»¹Ã»ÓÐË¢ÐÂÍêÒ»ÕÅͼƬʱ£¬GPUäÖȾ³öµÄÁíÒ»ÕÅͼƬÒѾËÍ´ï²¢¸²¸ÇÁËǰһÕÅ£¬µ¼ÖÂÆÁÄ»ÉÏ»ÃæµÄ˺ÁÑ£¬Ò²¾ÍÊÇÊÇÉϰ벿·ÖÊÇǰһÕÅͼƬ£¬Ï°벿·ÖÊǺóÒ»ÕÅͼƬ£º

PCÓÎÏ·Öнâ¾öÕâ¸öÎÊÌâµÄ·½·¨ÊÇ¿ªÆô´¹Ö±Í¬²½(v-sync)£¬Ò²¾ÍÊÇÈÃGPUÍ×У¬GPUäÖȾͼƬ±ØÐëÔÚÆÁÄ»Á½´ÎË¢ÐÂÖ®¼ä£¬ÇÒ±ØÐëµÈ´ýÆÁÄ»·¢³öµÄ´¹Ö±Í¬²½Ðźš£µ«ÕâÑùͬÑùÒ²ÊÇÒª¸¶³ö´ú¼ÛµÄ£º½µµÍÁËGPUµÄÊä³öƵÂÊ£¬Ò²¾Í½µµÍÁË»ÃæµÄÖ¡Êý¡£ÒÔÖÁÓÚÄãÔÚÍæÐèÒª¸ßÖ¡ÊýÔËÐеÄÓÎϷʱ(±ÈÈ羺ËÙ¡¢µÚÒ»È˳ÆÉä»÷)¸Ð¾õµ½¡°¶Ù¿¨¡±£¬ÒòΪµôÖ¡¡£
requestAnimationFrame
ÔÚÕâÀﲻ̸requestAnimationFrame(ÒÔϼò³ÆrAF)Ó÷¨£¬¾ßÌåÇë²Î¿¼MDN:Window.requestAnimationFrame()¡£ÎÒÃÇÀ´¾ßÌå̸̸rAFËù½â¾öµÄÎÊÌâ¡£
´ÓÉÏÒ»½ÚÎÒÃÇ¿ÉÒÔ×ܽá³öʵÏÖÆ½»¬¶¯»µÄÁ½¸öÒòËØ
1.ʱ»ú(Frame Timing)£º еÄÒ»Ö¡×¼±¸ºÃµÄʱ»ú
2.³É±¾(Frame Budget)£º äÖȾеÄÒ»Ö¡ÐèÒª¶à³¤µÄʱ¼ä
Õâ¸öNative API°ÑÎÒÃÇ´Ó¾À½áÓÚ¶à¾ÃˢеÄÒ»´ÎµÄÀ§¾³Öнâ¾È³öÀ´(ÆäʵrAFÒ²²»¹ØÐľàÀëÏÂ´ÎÆÁĻˢÐÂÒ³Ãæ»¹ÐèÒª¶à¾Ã)¡£µ±ÎÒÃǵ÷ÓÃÕâ¸öº¯ÊýµÄʱºò£¬ÎÒÃǸæËßËüÐèÒª×öÁ½¼þÊ£º
1. ÎÒÃÇÐèҪеÄÒ»Ö¡£»2.µ±ÄãäÖȾеÄһ֡ʱÐèÒªÖ´ÐÐÎÒ´«¸øÄãµÄ»Øµ÷º¯Êý
ÄÇôËü½â¾öÁËÎÒÃÇÉÏÃæÃèÊöµÄµÚÒ»¸öÎÊÌ⣬²úÉúеÄÒ»Ö¡µÄʱ»ú¡£
ÄÇôµÚ¶þ¸öÎÊÌâÄØ¡£²»£¬ËüÎÞÄÜΪÁ¦¡£±ÈÈç¿ÉÒÔ¶Ô±ÈÏÂÃæÁ½¸öÒ³Ãæ£º
¶Ô±ÈÁ½¸öÒ³ÃæµÄÔ´Â룬Äã»á·¢ÏÖÖ»ÓÐÒ»´¦²»Í¬£º
// animation loop function update(timestamp) { for(var m = 0; m < movers.length; m++) { // DEMO °æ±¾ //movers[m].style.left = ((Math.sin(movers[m].offsetTop + timestamp/1000)+1) * 500) + 'px';
// FIXED °æ±¾
movers[m].style.left = ((Math.sin(m + timestamp/1000)+1)
* 500) + 'px';
}
rAF(update);
};
rAF(update); |
DEMO°æ±¾Ö®ËùÒÔÂýµÄÔÒòÊÇ£¬ÔÚÐÞ¸Äÿһ¸öÎïÌåµÄleftֵʱ£¬»áÇëÇóÕâ¸öÎïÌåµÄoffsetTopÖµ¡£ÕâÊÇÒ»¸ö·Ç³£ºÄʱµÄreflow²Ù×÷(¾ßÌ廹ÓÐÄÄЩºÄʱµÄreflow²Ù×÷¿ÉÒԲο¼ÕâÆª:How
(not) to trigger a layout in WebKit)¡£ÕâÒ»µã´ÓChromeµ÷ÊÔ¹¤¾ßÖпÉÒÔ¿´³öÀ´(½ØÍ¼ÖеÄijЩ¹¦ÄÜÐèÒªÔÚChrome
canary°æ±¾ÖÐ²Å¿ÉÆôÓÃ)
δ½ÃÕýµÄ°æ±¾

¿É¼û´ó²¿·Öʱ¼ä¶¼»¨ÔÚÁËrenderingÉÏ£¬¶ø½ÃÕýÖ®ºóµÄ°æ±¾£º

renderingʱ¼ä´ó´ó¼õÉÙÁË
µ«Èç¹ûÄãµÄ»Øµ÷º¯ÊýºÄÊ±ÕæµÄºÜÑÏÖØ£¬rAF»¹ÊÇ¿ÉÒÔΪÄã×öһЩʲôµÄ¡£±ÈÈçµ±Ëü·¢ÏÖÎÞ·¨Î¬³Ö60fpsµÄƵÂÊʱ£¬Ëü»á°ÑƵÂʽµµÍµ½30fps£¬ÖÁÉÙÄܹ»±£³ÖÖ¡ÊýµÄÎȶ¨£¬±£³Ö¶¯»µÄÁ¬¹á¡£
ʹÓÃrAFÍÆ³Ù´úÂë
ûÓÐʲôÊÇÍòÄܵģ¬Ãæ¶ÔÉÏÃæµÄÇé¿ö£¬ÎÒÃÇÐèÒª¶Ô´úÂë½øÐÐ×éÖ¯ºÍÓÅ»¯¡£
¿´¿´ÏÂÃæÕâÑùÒ»¶Î´úÂ룺
function jank(second) { var start = +new Date(); while (start + second * 1000 > (+new Date())) {} }
div.style.backgroundColor = "red";
// some long run task
jank(5);
div.style.backgroundColor = "blue"; |
ÎÞÂÛÔÚÈκεÄä¯ÀÀÆ÷ÖÐÔËÐÐÉÏÃæµÄ´úÂ룬Äã¶¼²»»á¿´µ½div±äΪºìÉ«£¬Ò³ÃæÍ¨³£»áÔÚ¼ÙËÀ5Ã룬ȻºóÈÝÆ÷±äΪÀ¶É«¡£ÕâÊÇÒòΪä¯ÀÀÆ÷µÄʼÖÕÖ»ÓÐÒ»¸öÏß³ÌÔÚÔËÐÐ(¿ÉÒÔÕâôÀí½â£¬ÒòΪjsÒýÇæÓëUIÒýÇæ»¥³â)¡£ËäÈ»Äã¸æËßä¯ÀÀÆ÷´Ëʱdiv±³¾°ÑÕɫӦ¸ÃΪºìÉ«£¬µ«ÊÇËü´Ëʱ»¹ÔÚÖ´Ðнű¾£¬ÎÞ·¨µ÷ÓÃUIÏ̡߳£
ÓÐÁËÕâ¸öǰÌᣬÎÒÃǽÓÏÂÀ´¿´Õâ¶Î´úÂ룺
var div = document.getElementById("foo");
var currentWidth = div.innerWidth;
div.style.backgroundColor = "blue";
// do some "long running" task, like
sorting data |
Õâ¸öʱºòÎÒÃDz»½ö½öÐèÒª¸üб³¾°ÑÕÉ«£¬»¹ÐèÒª»ñÈ¡ÈÝÆ÷µÄ¿í¶È¡£¿ÉÒÔÏëÏóËüµÄÖ´ÐÐ˳ÐòÈçÏ£º

µ±ÎÒÃÇÇëÇóinnerWidthÒ»ÀàµÄÊôÐÔʱ£¬ä¯ÀÀÆ÷»áÒÔΪÎÒÃÇÂíÉÏÐèÒª£¬ÓÚÊÇËü»áÁ¢¼´¸üÐÂÈÝÆ÷µÄÑùʽ(ͨ³£ä¯ÀÀÆ÷»áÔÜ×ÅÒ»Åú£¬µÈ´ýʱ»úÒ»´ÎÐÔµÄrepaint£¬ÒÔ±ã½ÚÊ¡ÐÔÄÜ)£¬²¢°Ñ¼ÆËãµÄ½á¹û¸æËßÎÒÃÇ¡£Õâͨ³£ÊÇÐÔÄÜÏûºÄÁ¿´óµÄ¹¤×÷¡£
µ«Èç¹ûÎÒÃDz¢·ÇÁ¢¼´ÐèÒªµÃµ½½á¹ûÄØ£¿
ÉÏÃæµÄ´úÂëÓÐÁ½´¦²»×㣬
¸üб³¾°ÑÕÉ«µÄ´úÂë¹ýÓÚÌáǰ£¬¸ù¾Ýǰһ¸öÀý×Ó£¬ÎÒÃÇÖªµÀ£¬¼´Ê¹ÔÚÕâÀï¸æÖªÁËä¯ÀÀÆ÷ÎÒÐèÒª¸üб³¾°ÑÕÉ«£¬ä¯ÀÀÆ÷ÖÁÉÙÒ²ÒªµÈµ½jsÔËÐÐÍê±Ï²ÅÄܵ÷ÓÃUIỊ̈߳»
¼ÙÉèºóÃæ²¿·ÖµÄlong runing´úÂë»áÆô¶¯Ò»Ð©Òì²½´úÂ룬±ÈÈçsetTimeout»òÕßAjaxÇëÇóÓÖ»òÕßweb-worker£¬ÄÇÓ¦¸Ã¾¡ÔçΪÃî¡£
×ÛÉÏËùÊö£¬Èç¹ûÎÒÃDz»ÊÇÄÇôÆÈÇеÄÐèÒªÖªµÀinnerWidth£¬ÎÒÃÇ¿ÉÒÔʹÓÃrAFÍÆ³ÙÕⲿ·Ö´úÂëµÄ·¢Éú£º
requestAnimationFrame(function(){ var el = document.getElementById("foo");
var currentWidth = el.innerWidth;
el.style.backgroundColor = "blue";
// ...
});
// do some "long running" task, like
sorting data |
¿É¼û¼´Ê¹ÎÒÃÇÔÚÕâÀïûÓÐʹÓõ½¶¯»£¬µ«ÈÔÈ»¿ÉÒÔʹÓÃrAFÓÅ»¯ÎÒÃǵĴúÂë¡£Ö´ÐеÄ˳Ðò»á±ä³É£º

ÔÚÕâÀïrAFµÄÓ÷¨±ä³ÉÁË£º°Ñ´úÂëÍÆ³Ùµ½ÏÂÒ»Ö¡Ö´ÐС£
ÓÐʱºòÎÒÃÇÐèÒª°Ñ´úÂëÍÆ³ÙµÄ¸üÔ¶£¬±ÈÈçÕâ¸öÑù×Ó£º

ÔÙ±ÈÈçÎÒÃÇÏëÒªÒ»¸öЧ¹û·ÖÁ½²½Ö´ÐУº1.divµÄdisplay±äΪblock£»2. divµÄtopÖµËõ¶ÌÒÆ¶¯µ½Ä³´¦¡£Èç¹ûÕâÁ½Ïî²Ù×÷¶¼·ÅÈëͬһ֡Öеϰ£¬ä¯ÀÀÆ÷»áͬʱ°ÑÕâÁ½Ïî¸ü¸ÄÓ¦ÓÃÓÚÈÝÆ÷£¬ÔÚͬһ֡ÄÚ¡£ÓÚÊÇÎÒÃÇÐèÒªÁ½Ö¡°ÑÕâÁ½Ïî²Ù×÷Çø·Ö¿ªÀ´£º
requestAnimationFrame(function(){ el.style.display = "block"; requestAnimationFrame(function(){ // fire off a CSS transition on its `top` property el.style.top = "300px"; }); }); |
ÕâÑùµÄд·¨ºÃÏñÓÐЩ²»Ì«½²¾¿£¬Kyle SimpsonÓÐÒ»¸ö¿ªÔ´ÏîÄ¿h5ive£¬Ëü°ÑÉÏÃæµÄÓ÷¨·â×°ÁËÆðÀ´£¬²¢ÇÒÌṩÁËAPI¡£ÊµÏÖÆðÀ´·Ç³£¼òµ¥£¬ÕªÒ»¶Î´úÂëÇÆÇÆ£º
function qID(){ var id; do { id = Math.floor(Math.random() * 1E9); } while (id in q_ids); return id; }
function queue(cb) {
var qid = qID();
q_ids[qid] = rAF(function(){
delete q_ids[qid];
cb.apply(publicAPI,arguments);
});
return qid;
}
function queueAfter(cb) {
var qid;
qid = queue(function(){
// do our own rAF call here because we want to
re-use the same `qid` for both frames
q_ids[qid] = rAF(function(){
delete q_ids[qid];
cb.apply(publicAPI,arguments);
});
});
return qid;
} |
ʹÓ÷½·¨£º
// ²åÈëÏÂÒ»Ö¡ id1 = aFrame.queue(function(){ text = document.createTextNode("##"); body.appendChild(text); });
// ²åÈëÏÂÏÂÒ»Ö¡
id2 = aFrame.queueAfter(function(){
text = document.createTextNode("!!");
body.appendChild(text);
}); |
ʹÓÃrAF½âñî´úÂë
ÏÈ´ÓÒ»¸ö2011ÄêtwitterÓöµ½µÄbug˵Æð¡£
µ±Ê±twitter¼ÓÈëÁËÒ»¸öй¦ÄÜ£º¡°ÎÞÏÞ¹ö¶¯¡±¡£Ò²¾ÍÊǵ±Ò³Ãæ¹öÖÁµ×²¿µÄʱºò£¬È¥¼ÓÔØ¸ü¶àµÄtwitter£º
$(window).bind('scroll', function () { if (nearBottomOfPage()) { // load more tweets ... } }); |
µ«ÊÇÔÚÕâ¸ö¹¦ÄÜÉÏÏßÖ®ºó£¬·¢ÏÖÁËÒ»¸öÑÏÖØµÄbug£º¾¹ý¼¸´Î¹ö¶¯µ½×îµ×²¿Ö®ºó£¬¹ö¶¯¾Í»á±äµÃÆæÂýÎޱȡ£
¾¹ýÅŲ鷢ÏÖ£¬ÔÀ´ÊÇÒ»ÌõÓï¾äÒýÆðµÄ£º$details.find(".details-pane-outer");
Õ⻹²»ÊÇÕæÕýµÄ×ï¿ý»öÊ×£¬ÕæÕýµÄÔÒòÊÇÒòΪËûÃǽ«Ê¹ÓõÄjQueryÀà¿â´Ó1.4.2Éý¼¶µ½ÁË1.4.4°æ¡£¶øÕâjQueryÆäÖÐÒ»¸öÖØÒªµÄÉý¼¶ÊǰÑSizzleµÄÉÏÏÂÎÄÑ¡ÔñÆ÷È«²¿Ì滻ΪÁËquerySelectorAll¡£µ«ÊÇÕâ¸ö½Ó¿ÚÔʵÏÖʹÓõÄÊÇgetElementsByClassName¡£ËäÈ»querySelectorAllÔڴ󲿷ÖÇé¿öÏÂÐÔÄÜ»¹ÊDz»´íµÄ¡£µ«ÔÚͨ¹ýClassÃû³ÆÑ¡ÔñÔªËØÕâÒ»ÏîÊÇÕ¼ÁËÏ·硣ÓÐÁ½¸ö¶Ô±È²âÊÔ¿ÉÒÔ¿´³öÀ´£º1.querySelectorAll
v getElementsByClassName2.jQuery Simple Selector
ͨ¹ýÕâ¸öbug£¬John Resig¸ø³öÁËÒ»Ìõ(ʵ¼ÊÉÏÊÇÁ½Ìõ£¬µ«ÊǽñÌìֻȡÓëÎÒÃÇ»°ÌâÓйصÄ)·Ç³£ÖØÒªµÄ½¨Òé
It¡¯s
a very, very, bad idea to attach handlers to the
window scroll event. |
ËûÏë±í´ïµÄÒâ˼ÊÇ£¬Ïñscroll£¬resizeÕâÒ»ÀàµÄʼþ»á·Ç³£Æµ·±µÄ´¥·¢£¬Èç¹û°ÑÌ«¶àµÄ´úÂë·Å½øÕâÒ»ÀàµÄ»Øµ÷º¯ÊýÖУ¬»áÑÓ³ÙÒ³ÃæµÄ¹ö¶¯£¬ÉõÖÁÔì³ÉÎÞ·¨ÏìÓ¦¡£ËùÒÔÓ¦¸Ã°ÑÕâÒ»Àà´úÂë·ÖÀë³öÀ´£¬·ÅÔÚÒ»¸ötimerÖУ¬Óмä¸ôµÄÈ¥¼ì²éÊÇ·ñ¹ö¶¯£¬ÔÙ×öÊʵ±µÄ´¦Àí¡£±ÈÈçÈçÏ´úÂ룺
var didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
// Check your page position and then
// Load in more results
}
}, 250) |
ÕâÑùµÄ×÷·¨ÀàËÆÓÚNicholas½«ÐèÒª³¤Ê±¼äÔËËãµÄÑ»··Ö½âΪ¡°Æ¬¡±À´½øÐÐÔËË㣺
// ¾ßÌå¿ÉÒԲο¼ËûдµÄ¡¶javascript¸ß¼¶³ÌÐòÉè¼Æ¡· // Ò²¿ÉÒԲο¼ËûµÄÕâÆª²©¿Í£º http://www.nczonline.net/blog/2009/01/13/speed-up-your-javascript-part-1/ function chunk(array, process, context){ var items = array.concat(); //clone the array setTimeout(function(){ var item = items.shift(); process.call(context, item);
if (items.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
} |
ÔÀíÆäʵÊÇÒ»ÑùµÄ£¬ÎªÁËÓÅ»¯ÐÔÄÜ¡¢ÎªÁË·ÀÖ¹ä¯ÀÀÆ÷¼ÙËÀ£¬½«ÐèÒª³¤Ê±¼äÔËÐеĴúÂë·Ö½âΪС¶ÎÖ´ÐУ¬Äܹ»Ê¹ä¯ÀÀÆ÷ÓÐʱ¼äÏìÓ¦ÆäËûµÄÇëÇó¡£
»Øµ½rAFÉÏÀ´£¬ÆäʵrAFÒ²¿ÉÒÔÍê³ÉÏàͬµÄ¹¦ÄÜ¡£±ÈÈç×î³õµÄ¹ö¶¯´úÂëÊÇÕâÑù£º
function onScroll() { update(); }
function update() {
// assume domElements has been declared
for(var i = 0; i < domElements.length; i++)
{
// read offset of DOM elements
// to determine visibility - a reflow
// then apply some CSS classes
// to the visible items - a repaint
}
}
window.addEventListener('scroll', onScroll, false); |
ÕâÊǺܵäÐ͵ķ´Àý£ºÃ¿Ò»´Î¹ö¶¯¶¼ÐèÒª±éÀúËùÓÐÔªËØ£¬¶øÇÒÿһ´Î±éÀú¶¼»áÒýÆðreflowºÍrepaint¡£½ÓÏÂÀ´ÎÒÃÇÒª×öµÄÊÂÇé¾ÍÊǰÑÕâЩ·ÑʱµÄ´úÂë´ÓupdateÖнâñî³öÀ´¡£
Ê×ÏÈÎÒÃÇÈÔÈ»ÐèÒª¸øscrollʼþÌí¼Ó»Øµ÷º¯Êý£¬ÓÃÓڼǼ¹ö¶¯µÄÇé¿ö£¬ÒÔ·½±ãÆäËûº¯ÊýµÄ²éѯ£º
var latestKnownScrollY = 0;
function onScroll() {
latestKnownScrollY = window.scrollY;
} |
½ÓÏÂÀ´°Ñ·ÖÀë³öÀ´µÄrepaint»òÕßreflow²Ù×÷È«²¿·ÅÈëÒ»¸öupdateº¯ÊýÖУ¬²¢ÇÒʹÓÃrAF½øÐе÷Óãº
function update() { requestAnimationFrame(update);
var currentScrollY = latestKnownScrollY;
// read offset of DOM elements
// and compare to the currentScrollY value
// then apply some CSS classes
// to the visible items
}
// kick off
requestAnimationFrame(update); |
Æäʵ½âñîµÄÄ¿µÄÒѾ´ïµ½ÁË£¬µ«»¹ÐèÒª×öһЩÓÅ»¯£¬±ÈÈç²»ÄÜÈÃupdateÎÞÏÞÖ´ÐÐÏÂÈ¥£¬ÐèÒªÉè±ê־λÀ´¿ØÖÆËüµÄÖ´ÐУº
var latestKnownScrollY = 0, ticking = false;
function onScroll() {
latestKnownScrollY = window.scrollY;
requestTick();
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(update);
}
ticking = true;
} |
²¢ÇÒÎÒÃÇʼÖÕÖ»ÐèÒªÒ»¸örAFʵÀýµÄ´æÔÚ£¬Ò²²»ÔÊÐíÎÞÏ޴εÄupdateÏÂÈ¥£¬ÓÚÊÇÎÒÃÇ»¹ÐèÒªÒ»¸ö³ö¿Ú£º
function update() { // reset the tick so we can // capture the next onScroll ticking = false;
var currentScrollY = latestKnownScrollY;
// read offset of DOM elements
// and compare to the currentScrollY value
// then apply some CSS classes
// to the visible items
}
// kick off - no longer needed! Woo.
// update(); |
|