ÕâÊÇ JavaScript ¿ò¼ÜϵÁеĵڶþÕ¡£ÔÚÕâÒ»ÕÂÀÎÒ´òËã½²Ò»ÏÂÔÚä¯ÀÀÆ÷ÀïµÄÒì²½´úÂ벻ִͬÐз½Ê½¡£Ä㽫Á˽ⶨʱÆ÷ºÍʼþÑ»·Ö®¼äµÄ²»Í¬²îÒ죬±ÈÈç
setTimeout ºÍ Promises¡£
Õâ¸öϵÁÐÊǹØÓÚÒ»¸ö¿ªÔ´µÄ¿Í»§¶Ë¿ò¼Ü£¬½Ð×ö NX¡£ÔÚÕâ¸öϵÁÐÀÎÒÖ÷Òª½âÊÍÒ»ÏÂд¸Ã¿ò¼Ü²»µÃ²»¿Ë·þµÄÖ÷ÒªÀ§ÄÑ¡£Èç¹ûÄã¶Ô
NX ¸ÐÐËȤ¿ÉÒԲιÛÎÒÃÇµÄ Ö÷Ò³¡£
Õâ¸öϵÁаüº¬ÒÔϼ¸¸öÕ½ڣº
ÏîÄ¿½á¹¹
¶¨Ê±Ö´ÐÐ (µ±Ç°Õ½Ú)
ɳÏä´úÂëÆÀ¹À
Êý¾Ý°ó¶¨½éÉÜ
Êý¾Ý°ó¶¨Óë ES6 ´úÀí
×Ô¶¨ÒåÔªËØ
¿Í»§¶Ë·ÓÉ
Òì²½´úÂëÖ´ÐÐ
Äã¿ÉÄܱȽÏÊìϤ Promise¡¢process.nextTick()¡¢setTimeout()£¬»òÐí»¹ÓÐ
requestAnimationFrame() ÕâЩÒì²½Ö´ÐдúÂëµÄ·½Ê½¡£ËüÃÇÄÚ²¿¶¼Ê¹ÓÃÁËʼþÑ»·£¬µ«ÊÇËüÃÇÔÚ¾«È·¼ÆÊ±·½ÃæÓÐһЩ²»Í¬¡£
ÔÚÕâÒ»ÕÂÀÎÒ½«½âÊÍËüÃÇÖ®¼äµÄ²»Í¬£¬È»ºó¸ø´ó¼ÒÑÝʾÔõÑùÔÚÒ»¸öÀàËÆ NX ÕâÑùµÄÏȽø¿ò¼ÜÀïÃæÊµÏÖÒ»¸ö¶¨Ê±ÏµÍ³¡£²»ÓÃÎÒÃÇÖØÐÂ×öÒ»¸ö£¬ÎÒÃǽ«Ê¹ÓÃÔÉúµÄʼþÑ»·À´´ïµ½ÎÒÃǵÄÄ¿µÄ¡£
ʼþÑ»·
ʼþÑ»·ÉõÖÁûÓÐÔÚ ES6 ¹æ·¶ÀïÌáµ½¡£JavaScript ×ÔÉíÖ»ÓÐÈÎÎñ(Job)ºÍÈÎÎñ¶ÓÁÐ(job
queue)¡£¸ü¼Ó¸´ÔÓµÄʼþÑ»·ÊÇÔÚ NodeJS ºÍ HTML5 ¹æ·¶Àï·Ö±ð¶¨ÒåµÄ£¬ÒòΪÕâÆªÊÇÕë¶Ôǰ¶ËµÄ£¬ÎÒ»áÔÚÏêϸ˵Ã÷ºóÕß¡£
ʼþÑ»·¿ÉÒÔ±»¿´×öij¸öÌõ¼þµÄÑ»·¡£Ëü²»Í£µÄѰÕÒеÄÈÎÎñÀ´ÔËÐС£Õâ¸öÑ»·ÖеÄÒ»´Îµü´ú½Ð×öÒ»¸öµÎ´ð(tick)¡£ÔÚÒ»´ÎµÎ´ðÆÚ¼äÖ´ÐеĴúÂë³ÆÎªÒ»´ÎÈÎÎñ(task)¡£
while (eventLoop.waitForTask()) { eventLoop.processNextTask() } |
ÈÎÎñÊÇͬ²½´úÂ룬Ëü¿ÉÒÔÔÚÑ»·Öе÷¶ÈÆäËüÈÎÎñ¡£Ò»¸ö¼òµ¥µÄµ÷ÓÃÐÂÈÎÎñµÄ·½Ê½ÊÇ setTimeout(taskFn)¡£²»¹ÜÔõÑù£¬
ÈÎÎñ¿ÉÄÜÓкܶàÀ´Ô´£¬±ÈÈçÓû§Ê¼þ¡¢ÍøÂç»òÕß DOM ²Ù×÷¡£

ÈÎÎñ¶ÓÁÐ
¸ü¸´ÔÓһЩµÄÊÇ£¬Ê¼þÑ»·¿ÉÒÔÓжà¸öÈÎÎñ¶ÓÁС£ÕâÀïÓÐÁ½¸öÔ¼ÊøÌõ¼þ£¬ÏàͬÈÎÎñÔ´µÄʼþ±ØÐëÔÚÏàͬµÄ¶ÓÁУ¬ÒÔ¼°ÈÎÎñ±ØÐë°´²åÈëµÄ˳Ðò½øÐд¦Àí¡£³ý´ËÖ®Í⣬ä¯ÀÀÆ÷¿ÉÒÔ×öÈκÎËüÏë×öµÄÊÂÇé¡£ÀýÈ磬Ëü¿ÉÒÔ¾ö¶¨½ÓÏÂÀ´´¦ÀíÄĸöÈÎÎñ¶ÓÁС£
while (eventLoop.waitForTask()) { const taskQueue = eventLoop.selectTaskQueue() if (taskQueue.hasNextTask()) { taskQueue.processNextTask() } } |
ÓÃÕâ¸öÄ£ÐÍ£¬ÎÒÃDz»Äܾ«È·µÄ¿ØÖƶ¨Ê±¡£Èç¹ûÓà setTimeout()ä¯ÀÀÆ÷¿ÉÄܾö¶¨ÏÈÔËÐÐÍêÆäËü¼¸¸ö¶ÓÁвÅÔËÐÐÎÒÃǵĶÓÁС£

΢ÈÎÎñ¶ÓÁÐ
ÐÒÔ˵ÄÊÇ£¬Ê¼þÑ»·»¹ÌṩÁËÒ»¸ö½Ð×ö΢ÈÎÎñ(microtask)¶ÓÁеĵ¥Ò»¶ÓÁС£µ±Ç°ÈÎÎñ½áÊøµÄʱºò£¬Î¢ÈÎÎñ¶ÓÁлáÇå¿Õÿ¸öµÎ´ðÀïµÄÈÎÎñ¡£
while (eventLoop.waitForTask()) { const taskQueue = eventLoop.selectTaskQueue() if (taskQueue.hasNextTask()) { taskQueue.processNextTask() } const microtaskQueue = eventLoop.microTaskQueue while (microtaskQueue.hasNextMicrotask()) { microtaskQueue.processNextMicrotask() } } |
×î¼òµ¥µÄµ÷ÓÃ΢ÈÎÎñµÄ·½·¨ÊÇ Promise.resolve().then(microtaskFn)¡£Î¢ÈÎÎñ°´ÕÕ²åÈë˳Ðò½øÐд¦Àí£¬²¢ÇÒÓÉÓÚ½ö´æÔÚÒ»¸ö΢ÈÎÎñ¶ÓÁУ¬ä¯ÀÀÆ÷²»»á°Ñʱ¼äŪÂÒÁË¡£
´ËÍ⣬΢ÈÎÎñ¿ÉÒÔµ÷¶ÈеÄ΢ÈÎÎñ£¬Ëü½«²åÈ뵽ͬһ¸ö¶ÓÁУ¬²¢ÔÚͬһ¸öµÎ´ðÄÚ´¦Àí¡£

»æÖÆRendering
×îºóÊÇ»æÖÆRenderingµ÷¶È£¬²»Í¬ÓÚʼþ´¦ÀíºÍ·Ö½â£¬»æÖƲ¢²»ÊÇÔÚµ¥¶ÀµÄºǫ́ÈÎÎñÍê³ÉµÄ¡£ËüÊÇÒ»¸ö¿ÉÒÔÔËÐÐÔÚÿ¸öÑ»·µÎ´ð½áÊøÊ±µÄËã·¨¡£
ÔÚÕâÀïä¯ÀÀÆ÷ÓÖÓÐÁËÐí¶à×ÔÓÉ£ºËü¿ÉÄÜÔÚÿ¸öÈÎÎñÒÔºó»æÖÆ£¬µ«ÊÇËüÒ²¿ÉÄÜÔںü¸°Ù¸öÈÎÎñ¶¼Ö´ÐÐÁËÒÔºóÒ²²»»æÖÆ¡£
ÐÒÔ˵ÄÊÇ£¬ÎÒÃÇÓÐ requestAnimationFrame()£¬ËüÔÚÏÂÒ»¸ö»æÖÆÖ®Ç°Ö´Ðд«µÝµÄº¯Êý¡£ÎÒÃÇ×îÖÕµÄʼþÄ£ÐÍÏñÕâÑù£º
while (eventLoop.waitForTask()) { const taskQueue = eventLoop.selectTaskQueue() if (taskQueue.hasNextTask()) { taskQueue.processNextTask() } const microtaskQueue = eventLoop.microTaskQueue while (microtaskQueue.hasNextMicrotask()) { microtaskQueue.processNextMicrotask() } if (shouldRender()) { applyScrollResizeAndCSS() runAnimationFrames() render() } } |
ÏÖÔÚÓÃÎÒÃÇËùÖªµÀ֪ʶÀ´´´½¨¶¨Ê±ÏµÍ³!
ÀûÓÃʼþÑ»·
ºÍ´ó¶àÊýÏÖ´ú¿ò¼ÜÒ»Ñù£¬NX Ò²ÊÇ»ùÓÚ DOM ²Ù×÷ºÍÊý¾Ý°ó¶¨µÄ¡£ÅúÁ¿²Ù×÷ºÍÒì²½Ö´ÐÐÒÔÈ¡µÃ¸üºÃµÄÐÔÄܱíÏÖ¡£»ùÓÚÒÔÉÏÀíÓÉÎÒÃÇÓÃ
Promises¡¢ MutationObservers ºÍ requestAnimationFrame()¡£
ÎÒÃÇËùÆÚÍûµÄ¶¨Ê±Æ÷ÊÇÕâÑùµÄ£º
´úÂëÀ´×ÔÓÚ¿ª·¢Õß
Êý¾Ý°ó¶¨ºÍ DOM ²Ù×÷ÓÉ NX À´Ö´ÐÐ
¿ª·¢Õß¶¨Òåʼþ¹³×Ó
ä¯ÀÀÆ÷½øÐлæÖÆ
²½Öè 1
NX ¼Ä´æÆ÷¶ÔÏó»ùÓÚ ES6 ´úÀí ÒÔ¼° DOM ±ä¶¯»ùÓÚMutationObserver (±ä¶¯¹Û²âÆ÷)ͬ²½ÔËÐÐ(ÏÂÒ»½ÚÏêϸ½éÉÜ)¡£
Ëü×÷Ϊһ¸ö΢ÈÎÎñÑÓ³ÙÖ±µ½²½Öè 2 Ö´ÐÐÒÔºó²Å×ö³ö·´Ó¦¡£Õâ¸öÑÓ³ÙÒѾÔÚPromise.resolve().then(reaction)
½øÐÐÁ˶ÔÏóת»»£¬²¢ÇÒËü½«Í¨¹ý±ä¶¯¹Û²âÆ÷×Ô¶¯ÔËÐС£
²½Öè 2
À´×Ô¿ª·¢ÕߵĴúÂë(ÈÎÎñ)ÔËÐÐÍê³É¡£Î¢ÈÎÎñÓÉ NX ¿ªÊ¼Ö´ÐÐËù×¢²á¡£ ÒòΪËüÃÇÊÇ΢ÈÎÎñ£¬ËùÒÔ°´ÐòÖ´ÐС£×¢Ò⣬ÎÒÃÇÈÔÈ»ÔÚͬһ¸öµÎ´ðÑ»·ÖС£
²½Öè 3
¿ª·¢Õßͨ¹ý requestAnimationFrame(hook) ֪ͨ NX ÔËÐй³×Ó¡£Õâ¿ÉÄÜÔڵδðÑ»·ºó·¢Éú¡£ÖØÒªµÄÊÇ£¬¹³×ÓÔËÐÐÔÚÏÂÒ»´Î»æÖÆÖ®Ç°ºÍËùÓÐÊý¾Ý²Ù×÷Ö®ºó£¬²¢ÇÒ
DOM ºÍ CSS ¸Ä±ä¶¼ÒѾÍê³É¡£
²½Öè 4
ä¯ÀÀÆ÷»æÖÆÏÂÒ»¸öÊÓͼ¡£ÕâÒ²ÓпÉÄÜ·¢ÉúÔڵδðÑ»·Ö®ºó£¬µ«ÊǾø¶Ô²»»á·¢ÉúÔÚÒ»¸öµÎ´ðµÄ²½Öè 3 ֮ǰ¡£
ÀμÇÔÚÐÄÀïµÄÊÂÇé
ÎÒÃÇÔÚÔÉúµÄʼþÑ»·Ö®ÉÏʵÏÖÁËÒ»¸ö¼òµ¥¶øÓÐЧµÄ¶¨Ê±ÏµÍ³¡£ÀíÂÛÉϽ²ËüÔËÐеĺܺ㬵«ÊÇ»¹ÊǺܴàÈõ£¬Ò»¸öÇá΢µÄ´íÎó¿ÉÄܻᵼÖºÜÑÏÖØµÄ
BUG¡£
ÔÚÒ»¸ö¸´ÔÓµÄϵͳµ±ÖУ¬×îÖØÒªµÄ¾ÍÊǽ¨Á¢Ò»¶¨µÄ¹æÔò²¢ÔÚÒÔºó±£³ÖËüÃÇ¡£ÔÚ NX ÖÐÓÐÒÔϹæÔò£º
ÓÀÔ¶²»Óà setTimeout(fn, 0) À´½øÐÐÄÚ²¿²Ù×÷
ÓÃÏàͬµÄ·½·¨À´×¢²á΢ÈÎÎñ
΢ÈÎÎñ½ö¹©ÄÚ²¿²Ù×÷
²»Òª¸ÉÔ¤¿ª·¢Õß¹³×ÓÔËÐÐʱ¼ä
¹æÔò 1 ºÍ 2
Êý¾Ý·´ÉäºÍ DOM ²Ù×÷½«°´ÕÕ²Ù×÷˳ÐòÖ´ÐС£ÕâÑùÖ»Òª²»»ìºÏ¾Í¿ÉÒԺܺõÄÑÓ³ÙËüÃǵÄÖ´ÐС£»ìºÏÖ´Ðлá³öÏÖĪÃûÆäÃîµÄÎÊÌâ¡£
setTimeout(fn, 0) µÄÐÐΪÍêÈ«²»¿ÉÔ¤²â¡£Ê¹Óò»Í¬µÄ·½·¨×¢²á΢ÈÎÎñÒ²»á·¢Éú»ìÂÒ¡£ÀýÈ磬ÏÂÃæµÄÀý×ÓÖÐ
microtask2 ²»»áÕýÈ·µØÔÚ microtask1 ֮ǰÔËÐС£
Promise.resolve().then().then(microtask1) Promise.resolve().then(microtask2) |

¹æÔò 3 ºÍ 4
·ÖÀ뿪·¢ÕߵĴúÂëÖ´ÐкÍÄÚ²¿²Ù×÷µÄʱ¼ä´°¿ÚÊǷdz£ÖØÒªµÄ¡£»ìºÏÕâÁ½ÖÖÐÐΪ»áµ¼Ö²»¿ÉÔ¤²âµÄÊÂÇé·¢Éú£¬²¢ÇÒËü»áÐèÒª¿ª·¢ÕßÁ˽â¿ò¼ÜÄÚ²¿¡£ÎÒÏëºÜ¶àǰ̨¿ª·¢ÕßÒѾÓйýÀàËÆ¾Àú¡£
½áÂÛ
Èç¹ûÄã¶Ô NX ¿ò¼Ü¸ÐÐËȤ£¬¿ÉÒԲιÛÎÒÃǵÄÖ÷Ò³¡£»¹¿ÉÒÔÔÚ GIT ÉÏÕÒµ½ÎÒÃǵÄÔ´´úÂë¡£ |