تصحيح أخطاء JavaScript غير المتزامنة باستخدام "أدوات مطوري البرامج في Chrome"

مقدمة

إحدى الميزات القوية التي تجعل لغة JavaScript فريدة من نوعها، وهي قدرتها على العمل بشكل غير متزامن عبر دوال معاودة الاتصال. يتيح لك تعيين استدعاءات غير متزامنة كتابة رمز برمجي مستند إلى الحدث ولكنه يجعل أيضًا تتبع الأخطاء تجربة شاقة نظرًا لأن JavaScript لا يتم تنفيذها بطريقة خطية.

لحسن الحظ، يمكنك الآن في "أدوات مطوري البرامج في Chrome" عرض حزمة الاستدعاء الكاملة لعمليات استدعاء JavaScript غير المتزامنة.

نظرة عامة تشويقية سريعة حول حزم المكالمات غير المتزامنة.
نظرة عامة تشويقية سريعة على حِزم المكالمات غير المتزامنة (سنقسم سير هذا العرض التوضيحي قريبًا.)

بعد تفعيل ميزة تكديس المكالمات غير المتزامنة في "أدوات مطوري البرامج"، ستتمكّن من التعمّق في حالة تطبيق الويب في مراحل زمنية مختلفة. يمكنك تتبُّع تتبُّع تسلسل استدعاء الدوال البرمجية بالكامل لبعض مستمعي الأحداث، setInterval وsetTimeout وXMLHttpRequest ووعود وrequestAnimationFrame وMutationObservers والمزيد.

أثناء تتبُّع تسلسل استدعاء الدوال البرمجية، يمكنك أيضًا تحليل قيمة أي متغير في هذه النقطة المحددة من تنفيذ وقت التشغيل. إنها مثل آلة الزمن لتعبيرات الساعة!

لنفعِّل هذه الميزة ونلقي نظرة على بعض هذه السيناريوهات.

تفعيل ميزة "تصحيح الأخطاء غير المتزامن" في Chrome

جرِّب هذه الميزة الجديدة من خلال تفعيلها في Chrome. انتقِل إلى لوحة المصادر في "أدوات مطوري البرامج في Chrome Canary".

بجانب لوحة حزمة المكالمات على يسار الصفحة، هناك مربّع اختيار جديد لخيار "غير متزامن". بدِّل مربّع الاختيار لتشغيل تصحيح الأخطاء غير المتزامن أو إيقافه. (على الرغم من أنه بعد تشغيله، قد لا تريد إيقافه مطلقًا.)

فعِّل ميزة غير متزامنة أو أوقفها.

تسجيل أحداث الموقّت المتأخر واستجابات XHR

لقد رأيت ذلك من قبل في Gmail:

يحاول Gmail إعادة محاولة إرسال رسالة إلكترونية.

إذا كانت هناك مشكلة أثناء إرسال الطلب (إما أن الخادم يواجه مشكلات أو هناك مشكلات في الاتصال بالشبكة من جانب العميل)، فسيحاول Gmail تلقائيًا إعادة إرسال الرسالة بعد مهلة قصيرة.

لمعرفة كيف يمكن لحزم المكالمات غير المتزامنة أن تساعدنا في تحليل أحداث الموقّتات المتأخرة واستجابات XHR، أعدنا إنشاء هذا التدفق باستخدام مثال وهمي لـ Gmail. يمكن العثور على رمز JavaScript الكامل في الرابط أعلاه ولكن التدفق على النحو التالي:

رسم بياني انسيابي مثالي على Gmail
في الرسم البياني أعلاه، تشكل الطرق المميزة باللون الأزرق النقاط الرئيسية لهذه الميزة الجديدة في "أدوات مطوّري البرامج" لتحقيق أكبر فائدة ممكنة بما أنّ هذه الطرق تعمل بشكل غير متزامن.

من خلال الاطّلاع فقط على لوحة "تكديس المكالمات" في الإصدارات السابقة من "أدوات مطوري البرامج"، ستقدّم لك نقطة الإيقاف في postOnFail() معلومات بسيطة حول المكان الذي تم طلب postOnFail() منه. لكن انظر إلى الفرق عند تشغيل المكدسات غير المتزامنة:

قبل
تم ضبط نقطة إيقاف في مثال وهمي لخدمة Gmail بدون تكديس مكالمات غير متزامنة.
تم تفعيل عدم مزامنة لوحة "حزمة المكالمات" بدون.

هنا يمكنك معرفة أنّه تم بدؤ "postOnFail()" من خلال معاودة اتصال AJAX ولكن لا تتوفّر معلومات إضافية.

بعد
نقطة إيقاف معيّنة في مثال وهمي لخدمة Gmail مع تكديس مكالمات غير متزامنة
لوحة "حزمة المكالمات" مع تفعيل المزامنة غير المتزامنة.

هنا يمكنك معرفة أنّه تم بدء طلب XHR من submitHandler(). ممتاز.

عند تفعيل حِزم المكالمات غير المتزامنة، يمكنك الاطّلاع على حِزم المكالمات بالكامل لمعرفة ما إذا كان قد تم إرسال الطلب من submitHandler() (الذي يحدث بعد النقر على الزر "إرسال") أو من retrySubmit() (يحدث بعد مهلة setTimeout()):

submitHandler()
نقطة إيقاف معيّنة في مثال وهمي لخدمة Gmail مع تكديس مكالمات غير متزامنة
retrySubmit()
نقطة توقف أخرى تم تعيينها في مثال Gmail وهمي مع تكدسات مكالمات غير متزامنة

مشاهدة التعبيرات بشكل غير متزامن

عند التنقّل في حزمة المكالمات بالكامل، سيتم أيضًا تحديث التعبيرات التي شاهدتها لتعكس الحالة التي كانت عليها في ذلك الوقت!

مثال على استخدام تعبيرات المشاهدة مع حزم استدعاءات aysnc

تقييم الرمز من النطاقات السابقة

بالإضافة إلى تعبيرات المشاهدة، يمكنك التفاعل مع الرمز من النطاقات السابقة مباشرةً في لوحة وحدة تحكُّم JavaScript في أدوات مطوّري البرامج.

تخيل أنك د. من وتحتاج إلى القليل من المساعدة في مقارنة الساعة من قبل وصولك إلى تارديس بـ "الآن". من وحدة تحكّم أدوات مطوّري البرامج، يمكنك بسهولة تقييم القيم من خلال نقاط تنفيذ مختلفة وتخزينها وإجراء عمليات حسابية بشأنها.

مثال على استخدام وحدة تحكّم JavaScript مع حزم استدعاءات aysnc.
استخدِم وحدة تحكُّم JavaScript مع حِزم الاستدعاءات غير المتزامنة لتصحيح أخطاء الرمز. يمكنك العثور على العرض التوضيحي أعلاه هنا.

إنّ البقاء ضمن أدوات مطوّري البرامج للتحكّم في التعبيرات سيوفّر لك الوقت بدلاً من الرجوع إلى رمز المصدر وإجراء التعديلات وإعادة تحميل المتصفّح.

ابتكار الحلول المستندة إلى الوعود المتعددة

إذا كنت تعتقد أنه من الصعب كشف تدفق Gmail التجريبي السابق بدون تفعيل ميزة تكديس المكالمات غير المتزامنة، فهل يمكنك أن تتخيل مدى صعوبة الأمر مع التدفقات غير المتزامنة الأكثر تعقيدًا مثل الوعود التسلسلية؟ دعنا نعيد النظر في المثال الأخير لبرنامج "جيك أرتشيبالد" التعليمي حول وعود JavaScript.

إليك صورة متحركة بسيطة للتنقل بين حزم المكالمات في مثال async-best-example.html من "جيك".

قبل
مثال على نقطة إيقاف تم ضبطها في وعود بدون تكديس طلبات غير متزامنة
تم تفعيل عدم مزامنة لوحة "حزمة المكالمات" بدون.

لاحظ كيف أن لوحة "حزمة المكالمات" قصيرة جدًا في المعلومات عند محاولة تصحيح أخطاء الوعود.

بعد
مثال على نقطة إيقاف تم ضبطها في الوعود مع تكديس طلبات غير متزامنة.
لوحة "حزمة المكالمات" مع تفعيل المزامنة غير المتزامنة.

ممتاز. هذه الوعود. الكثير من عمليات معاودة الاتصال.

احصل على إحصاءات حول الصور المتحركة على الويب

دعنا نتعمق أكثر في أرشيفات HTML5Rocks. هل تذكرون "بول لويس" Leaner, Meaner, Faster Animations with requestAnimationFrame؟

افتح العرض التوضيحي لـ requestAnimationFrame وإضافة نقطة إيقاف في بداية طريقة update() (حوالي السطر 874) في post.html. باستخدام حزم المكالمات غير المتزامنة، نحصل على مزيد من الإحصاءات حول requestAnimationFrame، بما في ذلك إمكانية الرجوع إلى عملية معاودة الاتصال بحدث الانتقال للأعلى أو للأسفل.

قبل
تم ضبط نقطة إيقاف في مثال requestAnimationFrame بدون تكديس طلبات غير متزامنة.
تم تفعيل عدم مزامنة لوحة "حزمة المكالمات" بدون.
بعد
تم ضبط نقطة إيقاف في مثال requestAnimationFrame مع تكدسات مكالمات غير متزامنة
ومع تفعيل المزامنة.

تعقب تحديثات DOM عند استخدام MutationMonitorer

تسمح لنا MutationObserver بملاحظة التغييرات في نموذج العناصر في المستند (DOM). في هذا المثال البسيط، عند النقر على الزرّ، يتم إلحاق عقدة DOM جديدة بـ <div class="rows"></div>.

أضِف نقطة إيقاف داخل nodeAdded() (السطر 31) في Demo.html. مع تفعيل "حِزم المكالمات غير المتزامنة"، يمكنك الآن توجيه حزمة المكالمات مرة أخرى خلال addNode() إلى حدث النقرة الأولى.

قبل
تم ضبط نقطة إيقاف في مثال mutationMonitorer بدون تكدسات استدعاءات غير متزامنة.
تم تفعيل عدم مزامنة لوحة "حزمة المكالمات" بدون.
بعد
تم ضبط نقطة إيقاف في مثال mutationMonitorer مع تكديس الاستدعاءات غير المتزامنة.
ومع تفعيل المزامنة.

نصائح لتصحيح أخطاء JavaScript في حِزم المكالمات غير المتزامنة

تسمية الدوال

إذا كنت تميل إلى تعيين جميع عمليات الاستدعاء كدوال مجهولة المصدر، يمكنك بدلاً من ذلك اختيار اسم لها لتسهيل عرض حزم المكالمات.

على سبيل المثال، خذ دالة مجهولة مثل هذه:

window.addEventListener('load', function() {
  // do something
});

وامنحه اسمًا مثل windowLoaded():

window.addEventListener('load', function <strong>windowLoaded</strong>(){
  // do something
});

عند تنشيط حدث التحميل، سيظهر في تتبُّع تسلسل استدعاء الدوال البرمجية في أدوات مطوّري البرامج مع اسم الدالة بدلاً من الكلمة الغامضة "(دالة مجهولة)". ويسهّل ذلك عليك الاطّلاع بنظرة سريعة على ما يحدث في تقرير تتبُّع تسلسل استدعاء الدوال البرمجية.

قبل
دالة مجهولة.
بعد
دالة مُسمّاة

استكشاف المزيد

باختصار، هذه هي جميع عمليات الاستدعاء غير المتزامنة التي ستعرض فيها أدوات مطوّري البرامج حزمة المكالمات الكاملة:

  • الموقّتات: يمكنك الرجوع إلى المكان الذي تم فيه إعداد setTimeout() أو setInterval().
  • XHR: يمكنك الرجوع إلى حيث تم استدعاء xhr.send().
  • إطارات الصور المتحركة: يمكنك الرجوع إلى حيث تمت استدعاء requestAnimationFrame.
  • الوعود: عليك العودة إلى المكان الذي حققنا فيه الوعود.
  • Object.observe: الرجوع إلى حيث تم ربط معاودة الاتصال بالمراقب في الأصل.
  • MutationObservers: عُد إلى المكان الذي تم فيه إطلاق حدث مراقب الطفرة.
  • window.postMessage(): تعرّف على مزيد من المعلومات حول مكالمات المراسلة داخل العمليات.
  • DataTransferItem.getAsString()
  • واجهة برمجة التطبيقات FileSystem
  • IndexedDB
  • WebSQL
  • أحداث DOM المؤهَّلة عبر addEventListener(): يمكنك الرجوع إلى المكان الذي بدأ فيه الحدث. لأسباب تتعلق بالأداء، ليست كل أحداث DOM مؤهلة لميزة تكديس الاستدعاءات غير المتزامنة. ومن أمثلة الأحداث المتاحة حاليًا: "التمرير" و"تغيير التجزئة" و"الاختيار".
  • فعاليات الوسائط المتعددة عبر addEventListener(): يمكنك الرجوع إلى المكان الذي بدأت فيه الفعالية. تشمل أحداث الوسائط المتعددة المتاحة ما يلي: أحداث الصوت والفيديو (مثل أحداث 'play' و'pause' و'ratechange') وأحداث WebRTC MediaStreamTrackList (مثل 'addtrack' و'removetrack') وأحداث MediaSource (مثل 'sourceopen').

يجب أن تكون قادرًا على رؤية تتبع تسلسل استدعاء الدوال البرمجية بالكامل لاستدعاءات JavaScript، بحيث لا تكون هذه الشعرة ظاهرة على رأسك. يمكن الاستفادة من هذه الميزة في أدوات مطوري البرامج بشكل خاص عند وقوع أحداث متعددة غير متزامنة في ما يتعلق ببعضها، أو في حال طرح استثناء غير مرصود من داخل استدعاء غير متزامن.

يمكنك تجربتها في Chrome. إذا كانت لديك أي ملاحظات حول هذه الميزة الجديدة، يُرجى مراسلتنا على أداة تتبُّع الأخطاء في "أدوات مطوري البرامج في Chrome" أو في مجموعة "أدوات مطوري البرامج في Chrome".