رهام رفیعی تهرانی
رهام رفیعی تهرانی
خواندن ۳ دقیقه·۱ سال پیش

آشنایی با micro task queue در javascript



بیاید با یک مثال شروع کنیم. به نظرتون خروجی کد زیر کدوم گزینه است؟


اگر با جاوا اسکریپت و event loop آشنا باشید میتونید که گزینه a نیست. جواب بین گزینه b و c هست.

اگر با micro task queue آشنا باشید میدونید چرا جواب c درسته و b غلط.


بریم تحلیلش کنیم:
اول از همه که عدد 1 پرینت میشه. عدد 2 در setTimeout هست و asynchronous اجرا میشه . بنابراین بلافاصله پرینت نمیشه و به task queue میره. بعدش عدد 3 پرینت میشه. promise ها هم asyncronous هستند. پس اجرای promise هم به task queue میره (!). بعد عدد 5 پرینت میشه.

به نظر میرسه که باید عدد 2 پرینت بشه و بعدش عدد 4. در حالیکه با اجرای این کد میبینیم که اول عدد 4 اجرا میشه و بعد عدد 2.
چرا ؟

جوابش به ساختار جاوااسکریپت در اجرای دستورات برمیگرده. Promise ها در صفی ذخیره میشوند بنام micro task queue. اعضای این صف بعد از اجرای همه callback های یک event، و قبل از اینکه جاوااسکریپت event loop را بررسی کند، اجرا میشوند. در واقع اعضای این صف با اولویت بالاتری اجرا میشوند.

در واقع بعد از اجرای console.log(5) ، اجرای اسکریپت فعلی تمام میشه و وقتشه جاوااسکریپت به صف task ها سر بزنه. ولی اول به micro task queue سر میزنه و میبینه یک Promise هست که باید صدا زده بشه.

بنابر این اول عدد ۴ اجرا میشه. event loop همچنان به micro queue task نگاه میکنه و تا زمانی که خالی نباشه سراغ task queue نمیره. با اجرای عدد ۴ و خالی شدن micro queue task ، حالا به سراغ task های عادی میره و console.log(2) رو اجرا میکنه.


بریم یک مثال دیگه ببینیم:

در این کد چه اتفاقی می افته؟ لطفا یک دور خودتون سعی کنین تحلیل کنین و بعد بیاین سراغ اتفاقی که واقعا می افته.قدم اول: نوبت به اجرای اسکریپت اصلی توسط event loop میرسه. اسکریپت اصلی به stack میره و اجراش شروع میشه.

قدم دوم: callback اول برای کلیک روی دکمه رجیستر میشه.

قدم سوم: callback دوم برای کلیک روی دکمه رجیستر میشه.

قدم چهارم: روی دکمه کلیک میشه و callback اول جهت اجرا شدن به stack میره.

دقت کنید که الان داخل stack هم اسکریپت اصلی رو داریم و هم callback اول رو داریم. تا وقتی button.click تموم نشه ، اسکریپت ما در حال اجراست.

قدم پنجم: دستور لاگ کردن Microtask1 میره در micro task queue میشینه

قدم ششم: دستور لاگ کردن Listener 1 اجرا میشه.

قدم هفتم و مهم ترین قسمت : اجرای callback اول تموم میشه و بر میگرده به اسکریپت اصلی.

قدم هشتم: callback دوم برای اجرا فراخوانی میشه و به stack میره.

قدم نهم: دستور لاگ کردن Microtask 2 میره در micro task queue میشینه.

قدم دهم: دستور لاگ کردن Listener 2 اجرا میشه.

قدم یازدهم: اجرای callback دوم هم تموم میشه و برمیگرده به اسکریپت اصلی.

قدم دوازدهم: اجرای button.click تموم میشه و به دنبالش اجرای اسکریپت اصلی تموم میشه.

قدم سیزدهم: قبل از اینکه سراغ task ها بره، میره سراغ micro task queue. داخل micro task queue یک task پیدا میکنه و دستور لاگ کردنMicrotask 1 رو اجرا میکنه.

قدم چهاردهم: هنوز micro task queue خالی نشده. پس task بعدیش رو اجرا میکنه و دستور لاگ کردن Microtask 2 رو اجرا کنه.

قدم پانزدهم: micro task queue خالی شده. پس میره سراغ task queue و باز هم چیزی نمی بینه و اجرای کد تموم میشه.

قدم شانزدهم: event loop همچنان منتظره تا رویداد جدیدی ثبت بشه.

خروجی :

Listener 1, Listener 2, Microtask 1, Microtask 2

مقاله های مرتبط:

تفاوت stopPropagation و stopImmediatePropagation


امیدوارم از این مقاله لذت ببرید و براتون مفید باشه.

اگر دوست دارید میتونید از طریق صفحه لینکدین با من در ارتباط باشید :)

javascriptfrontendفرانت اند
برنامه نویسی یک شغل نیست، یک هنره.
شاید از این پست‌ها خوشتان بیاید