التعمق في المياه الضبابية أثناء تحميل النصوص

مقدمة

في هذه المقالة، سأعلّمك كيفية تحميل بعض JavaScript في المتصفّح وتنفيذه.

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

بالنسبة إلى المبتدئين، إليك كيفية تحديد المواصفات الطرق المختلفة التي يمكن بها تنزيل النص البرمجي وتنفيذه:

WHATWG بشأن تحميل النصوص البرمجية
WHATWG بشأن تحميل النصوص البرمجية

كما هو الحال مع جميع مواصفات WhatWG، يبدو الأمر في البداية كما لو تداعيات قنبلة عنقودية في مصنع خربشة، ولكن بعد قراءته للمرة الخامسة ومحو الدماء من عينيك، سيكون الأمر مثيرًا للاهتمام حقًا:

يتضمّن النص الأول ما يلي:

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

يا لها من بساطة رائعة. في هذه الحالة، سينزِّل المتصفّح كلا النصَّين البرمجيَّين بشكل موازٍ وينفِّذهما في أقرب وقت ممكن مع الحفاظ على ترتيبهما. لن يتم تنفيذ ‎“2.js” إلا بعد تنفيذ ‎“1.js” (أو تعذّر تنفيذه)، ولن يتم تنفيذ ‎“1.js” إلا بعد تنفيذ النص البرمجي أو جدول الأنماط السابق، وما إلى ذلك.

ولسوء الحظ، يحظر المتصفح العرض الإضافي للصفحة أثناء حدوث كل ذلك. ويعود السبب في ذلك إلى واجهات برمجة تطبيقات DOM من "العصر الأول للويب" التي تسمح بإلحاق سلاسل إلى المحتوى الذي يعالجه المُحلِّل، مثل document.write. ستواصل المتصفّحات الأحدث فحص المستند أو تحليله في الخلفية وبدء عمليات تنزيل للمحتوى الخارجي الذي قد يحتاجه (مثل JavaScript والصور وCSS وما إلى ذلك)، ولكن سيظلّ عرض المحتوى محظورًا.

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

شكرًا، إيهاب (لا، لستُ ساخرًا)

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

لاحظت Microsoft هذه المشاكل في الأداء وأدخَلت ميزة "التأجيل" في Internet Explorer 4. يعني هذا أساسًا "أتعهد بعدم إدخال عناصر في المدقّق باستخدام عناصر مثل document.write. إذا خالفت هذا الوعد، يمكنك معاقبتي بأي طريقة تراها مناسبة". تم تضمين هذه السمة في HTML4 وظهرت في متصفّحات أخرى.

في المثال أعلاه، سينزِّل المتصفّح كلا النصَّين البرمجيَّين بالتوازي وينفِّذهما قبل بدء تنفيذ DOMContentLoaded مباشرةً، مع الحفاظ على ترتيبهما.

مثل قنبلة عنقودية في مصنع للأغنام، أصبحت "تأخير" عبارة عن فوضى متشابكة. لدينا 6 أنماط لإضافة نص برمجي، بين سمتَي "src" و"defer" وبين علامات النص البرمجي مقابل النصوص البرمجية المضافة ديناميكيًا. بالطبع، لم تتفق المتصفّحات على الطلب الذي يجب تنفيذه. كتبت Mozilla مقالة رائعة حول هذه المشكلة كما ظهرت في عام 2009.

جعلت WHG هذا السلوك صريحًا، وأعلنت أن "تأجيل" ليس له أي تأثير على النصوص البرمجية التي تمت إضافتها ديناميكيًا أو تفتقر إلى "src". وبخلاف ذلك، يجب تشغيل النصوص البرمجية المؤجلة بعد تحليل المستند، بالترتيب الذي تمت إضافتها به.

شكرًا، إيهاب (حسنًا، الآن أتحدث بسخرية)

فهو يسبِّب بشيء يبرّره. هناك خلل سيئ في IE4-9 يمكن أن يتسبب في تنفيذ النصوص البرمجية بترتيب غير متوقع. إليك ما يحدث:

1.js

console.log('1');
document.getElementsByTagName('p')[0].innerHTML = 'Changing some content';
console.log('2');

2.js

console.log('3');

بافتراض توفّر فقرة في الصفحة، يكون الترتيب المتوقّع للسجلّات هو [1، 2، 3]، على الرغم من أنّه في IE9 والإصدارات الأقدم، يظهر الترتيب على النحو التالي: [1، 3، 2]. تؤدي عمليات معيّنة في DOM إلى إيقاف تنفيذ النص البرمجي الحالي مؤقتًا وتنفيذ النصوص البرمجية الأخرى المعلّقة قبل المتابعة.

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

استخدام HTML5 لتقديم المساعدة

<script src="//other-domain.com/1.js" async></script>
<script src="2.js" async></script>

وفّرت لنا لغة HTML5 سمة جديدة، وهي "async"، والتي تفترض أنّك لن تستخدم document.write، ولكنّها لا تنتظر حتى يتم تحليل المستند لتنفيذه. سينزِّل المتصفّح كلا النصَّين البرمجيَّين بشكل موازٍ وينفِّذهما في أقرب وقت ممكن.

بسبب أنّه سيتم تنفيذهما في أقرب وقت ممكن، قد يتم تنفيذ ‎“2.js” قبل ‎“1.js”. لا بأس بذلك إذا كانا مستقلّين، فربما يكون ‎“1.js” نصًا برمجيًا للتتبّع لا علاقة له بـ ‎“2.js”. ولكن إذا كان ‎“1.js” نسخة من jQuery على شبكة توصيل المحتوى (CDN) تعتمد عليها ‎“2.js”، ستظهر أخطاء على صفحتك، مثل قنبلة عنقودية في… لا أعرف… ليس لدي أيّ تفسير لذلك.

أعرف ما نحتاجه، مكتبة JavaScript.

الهدف الرئيسي هو تنزيل مجموعة من النصوص البرمجية على الفور بدون حظر العرض وتنفيذه في أقرب وقت ممكن بالترتيب الذي تمت إضافته به. للأسف، لا يسمح لك تنسيق HTML بإجراء ذلك.

تم حلّ المشكلة باستخدام JavaScript بأشكال مختلفة. وقد تطلب منك بعض التطبيقات إجراء تغييرات على JavaScript، من خلال لفّها في دالة استدعاء تستدعيها المكتبة بالترتيب الصحيح (مثل RequireJS). وكان الآخرون يستخدمون XHR للتنزيل بشكل موازٍ ثم eval() بالترتيب الصحيح، ما لم يكن لديهم عنوان CORS وكان المتصفّح متوافقًا معه. واستخدم البعض حيلاً رائعة جدًا، مثل برنامج LabJS.

كانت عمليات الاختراق تتضمن خداع المتصفّح لتنزيل المورد بطريقة تؤدي إلى بدء حدث عند اكتمال التنزيل، ولكن مع تجنُّب تنفيذه. في LabJS، ستتم إضافة النص البرمجي بنوع MIME غير صحيح، مثل <script type="script/cache" src="...">. بعد تنزيل جميع النصوص البرمجية، ستتم إضافتها مرة أخرى بنوع صحيح، على أمل أن يحصل المتصفّح عليها مباشرةً من ذاكرة التخزين المؤقت وينفّذها على الفور بالترتيب. وكان هذا الإجراء يعتمد على سلوك ملائم ولكن غير محدّد، وتعطّل عندما أعلنت HTML5 أنّ المتصفحات يجب ألا تنزّل نصوص برمجية بنوع غير معروف. تجدر الإشارة إلى أنّ LabJS تكيّف مع هذه التغييرات ويستخدم الآن مجموعة من الطرق الواردة في هذه المقالة.

ومع ذلك، تواجه أدوات تحميل النصوص البرمجية مشكلة في الأداء، وعليك الانتظار إلى أن يتم تنزيل JavaScript الخاص بالمكتبة وتحليله قبل أن يبدأ تنزيل أي من النصوص البرمجية التي تُديرها. أيضًا، كيف سنقوم بتحميل برنامج تحميل النصوص البرمجية؟ كيف سنحمّل النص البرمجي الذي يُخبر أداة تحميل النصوص البرمجية بما يجب تحميله؟ من يشاهد محتوى Watchmen؟ لماذا أنا عارٍ؟ هذه كلها أسئلة صعبة.

بوجهٍ عام، إذا كان عليك تنزيل ملف نصي إضافي قبل التفكير في تنزيل نصوص أخرى، يعني ذلك أنّك خسرت معركة الأداء على الفور.

نموذج DOM لإنقاذ الموقف

يمكن العثور على الإجابة في مواصفات HTML5، إلا أنّها مخفية في أسفل قسم تحميل النصوص البرمجية.

لنترجم ذلك إلى "كائن من الأرض":

[
  '//other-domain.com/1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  document.head.appendChild(script);
});

النصوص البرمجية التي يتم إنشاؤها ديناميكيًا وإضافتها إلى المستند تكون غير متزامنة تلقائيًا، ولا تحظر العرض والتنفيذ فور تنزيلها، ما يعني أنّها قد تظهر بترتيب غير صحيح. ومع ذلك، يمكننا وضع علامة صراحةً على أنّها غير متزامنة:

[
  '//other-domain.com/1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

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

يجب تضمين النص البرمجي أعلاه بشكل مضمّن في رأس الصفحات، ووضع تنزيلات النصوص البرمجية في قائمة انتظار في أقرب وقت ممكن بدون تعطيل العرض التدريجي، وتنفيذه في أقرب وقت ممكن بالترتيب الذي حدّدته. يمكن تنزيل ملف ‎“2.js” قبل ملف ‎“1.js” مجانًا، ولكن لن يتم تنفيذه إلا بعد تنزيل ملف ‎“1.js” وتنفيذه بنجاح أو تعذُّر تنفيذ أي منهما. مرحبًا، تم تنزيل الملفات بشكل غير متزامن ولكن تم تنفيذها بالترتيب.

يتوافق تحميل النصوص البرمجية بهذه الطريقة مع كل العناصر التي تتوافق مع السمة غير المتزامنة، باستثناء Safari 5.0 (يمكن استخدام 5.1). بالإضافة إلى ذلك، جميع إصدارات Firefox وOpera متوافقة، لأنّ الإصدارات التي لا تتيح استخدام السمة async تنفِّذ النصوص البرمجية المُضافة ديناميكيًا بالترتيب الذي تمت إضافتها به إلى المستند على أي حال.

هل هذه هي أسرع طريقة لتحميل النصوص البرمجية؟ أليس كذلك؟

حسنًا، إذا كنت تحدّد بشكل ديناميكي النصوص البرمجية التي سيتم تحميلها، نعم، وإلا فلن يتم ذلك. في المثال أعلاه، على المتصفّح تحليل النص البرمجي وتنفيذه لمعرفة النصوص البرمجية التي يجب تنزيلها. يؤدي ذلك إلى إخفاء نصوصك البرمجية عن برامج فحص التحميل المُسبَق. وتستخدم المتصفّحات هذه الماسحات الضوئية لاكتشاف المراجع على الصفحات التي يُرجّح أن تزورها بعد ذلك، أو لاكتشاف مراجع الصفحة عندما يكون المُحلِّل محظورًا من قِبل مرجع آخر.

يمكننا إضافة قابلية الاكتشاف مرة أخرى من خلال وضع ما يلي في رأس المستند:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

يُعلم هذا المتصفّح بأنّ الصفحة تحتاج إلى 1.js و2.js. تشبه الدالة link[rel=subresource] الدالة link[rel=prefetch]، ولكنّها ذات دلالات مختلفة. لا يتوفّر هذا الخيار حاليًا إلا في Chrome، وعليك تحديد النصوص البرمجية التي تريد تحميلها مرّتين، مرّة واحدة من خلال عناصر الرابط ومرّة أخرى في النص البرمجي.

تصحيح: لقد ذكرت في الأصل أنّ هذه الملفات يتم رصدها بواسطة أداة فحص التحميل المُسبَق، ولكنّها لا يتم رصدها بهذه الطريقة، بل يتم رصدها بواسطة المعالج العادي. ومع ذلك، يمكن أن يكتشف برنامج فحص التحميل المسبق هذه الأشياء، إلا أنها لم تفعل ذلك بعد، في حين أنه لا يمكن مطلقًا تحميل النصوص البرمجية المضمنة بواسطة التعليمات البرمجية التنفيذية. شكرًا يواف ويس الذي صحّح معلوماتي في التعليقات.

أجد هذه المقالة مزعجة

إنّ هذا الموقف مزعج ومن الطبيعي أن تشعر بالضيق. ما مِن طريقة غير متكرّرة وتعريفية لتنزيل النصوص البرمجية بسرعة وبشكل غير متزامن أثناء التحكّم في ترتيب التنفيذ. باستخدام HTTP2/SPDY، يمكنك تقليل الوقت المستغرَق في معالجة الطلبات إلى الحدّ الذي يجعل من إرسال النصوص البرمجية في ملفات صغيرة متعددة قابلة للتخزين المؤقت بشكلٍ فردي أسرع طريقة. تخيل ما يلي:

<script src="dependencies.js"></script>
<script src="enhancement-1.js"></script>
<script src="enhancement-2.js"></script>
<script src="enhancement-3.js"></script>
…
<script src="enhancement-10.js"></script>

يتعامل كل نص برمجي لتحسين مع مكوّن صفحة معيّن، ولكنه يتطلّب دوالّ مساعدة في dependencies.js. من الناحية المثالية، نريد تنزيل جميع العناصر بشكل غير متزامن، ثم تنفيذ النصوص البرمجية للتحسين في أقرب وقت ممكن، وبأي ترتيب، ولكن بعد السمة التابعة لها.js. إضافة إلى التحسينات التدريجية لا تتوفّر طريقة تعريفية لتحقيق ذلك ما لم يتم تعديل النصوص البرمجية نفسها لتتبُّع حالة تحميل dependencies.js. ولا يؤدي استخدام async=false إلى حلّ هذه المشكلة، لأنّ تنفيذ enhancement-10.js سيتم حظره من 1 إلى 9. في الواقع، هناك متصفّح واحد فقط يتيح إجراء ذلك بدون استخدام أساليب خداعية…

لدى IE فكرة.

يُحمِّل Internet Explorer النصوص البرمجية بشكل مختلف عن المتصفّحات الأخرى.

var script = document.createElement('script');
script.src = 'whatever.js';

يبدأ Internet Explorer في تنزيل whatever.js الآن، ولا تبدأ المتصفّحات الأخرى في التنزيل إلى أن تتم إضافة النص البرمجي إلى المستند. يتضمّن IE أيضًا الحدث "readystatechange" والسمة "readystate" الذي يطلعنا على مستوى تقدّم التحميل. وهذا مفيد جدًا، لأنّه يتيح لنا التحكّم في تحميل النصوص البرمجية وتنفيذها بشكل مستقل.

var script = document.createElement('script');

script.onreadystatechange = function() {
  if (script.readyState == 'loaded') {
    // Our script has download, but hasn't executed.
    // It won't execute until we do:
    document.body.appendChild(script);
  }
};

script.src = 'whatever.js';

يمكننا إنشاء نماذج تبعية معقدة عن طريق اختيار وقت إضافة النصوص إلى المستند. يتيح متصفّح Internet Explorer هذا النموذج منذ الإصدار 6. هذا أمر مثير للاهتمام، ولكنّه لا يزال يواجه مشكلة اكتشاف أداة التحميل المُسبَق نفسها التي تواجهها async=false.

يكفي. كيف أقوم بتحميل النصوص البرمجية؟

حسنًا. إذا كنت تريد تحميل النصوص البرمجية بطريقة لا تحظر العرض ولا تتضمّن التكرار وتتضمّن دعمًا ممتازًا للنصوص البرمجية، إليك ما أقترحه:

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

هذا كلّ ما في الأمر. في نهاية عنصر النص نعم، إنّ العمل كمطوّر مواقع إلكترونية يشبه إلى حد كبير عمل الملك سيزيفوس (بوم! 100 نقطة عصرية كمرجع للأساطير اليونانية). إنّ القيود المفروضة على HTML والمتصفّحات تمنعنا من تحقيق نتائج أفضل بكثير.

آمل أن تساعدنا وحدات JavaScript من خلال توفير طريقة توضيحية غير محظورة لتحميل النصوص البرمجية ومنح إمكانية التحكّم في ترتيب التنفيذ، على الرغم من أنّ ذلك يتطلّب كتابة النصوص البرمجية كوحدات.

هل هناك طريقة أفضل يمكننا استخدامها الآن؟

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

أولاً، نضيف بيان المورد الفرعي لأدوات التحميل المُسبق:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

بعد ذلك، في القسم العلوي من المستند، نحمِّل النصوص البرمجية باستخدام JavaScript، باستخدام async=false، مع الرجوع إلى طريقة تحميل النصوص البرمجية المستندة إلى حالة الاستعداد في Internet Explorer، مع الرجوع إلى طريقة التأخير.

var scripts = [
  '1.js',
  '2.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we'll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

في ما يلي بعض الحيل والتصغير، وهي 362 بايت مع عناوين URL الخاصة بالنص البرمجي:

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

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

أوه، تعرفت الآن على سبب اتساع قسم تحميل نص whatWG. أحتاج إلى مشروب.

مرجع سريع

عناصر النصوص البرمجية البسيطة

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

ما ورد في المواصفات: يتم تنزيلها معًا وتنفيذها بالترتيب بعد أي ملفات CSS في انتظار المراجعة، ومنع العرض إلى أن تكتمل. المتصفّحات: نعم يا سيدي

تأجيل

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

تقول المواصفات: التنزيل معًا وتنفيذ بالترتيب قبل DOMContentLoaded مباشرةً. تجاهل "defer" في النصوص البرمجية التي لا تحتوي على "src". يعرض IE 10 والإصدارات الأقدم ما يلي: قد نفِّذ 2.js في منتصف تنفيذ 1.js. أليس هذا ممتعًا؟ يشير المتصفّحات باللون الأحمر إلى ما يلي: ليس لديّ أي فكرة عن هذا الإجراء "تأخير"، سأحمّل النصوص البرمجية كما لو لم تكن موجودة. المتصفّحات الأخرى: حسنًا، ولكن قد لا أتجاهل "defer" في النصوص البرمجية التي لا تحتوي على "src".

غير متزامنة

<script src="//other-domain.com/1.js" async></script>
<script src="2.js" async></script>

ما ورد في المواصفات: يتم تنزيلها معًا وتنفيذها بالترتيب الذي يتم تنزيلها به. تظهر المتصفّحات التي تظهر باللون الأحمر على النحو التالي: ما هي "غير متزامن"؟ سأحمّل النصوص البرمجية كما لو لم تكن موجودة. ما يقوله المتصفّح الآخر: حسنًا.

Async false

[
  '1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

البيانات المحدّدة: يتم تنزيلها معًا، وتنفيذها بالترتيب بعد تنزيلها بالكامل. Firefox < 3.6، Opera: ليس لديّ أي فكرة عن هذا العنصر "غير المتزامن"، ولكن يحدث أنّني أُنفّذ النصوص البرمجية المُضافة من خلال JS بالترتيب الذي تمت إضافتها به. يُظهر Safari 5.0 ما يلي: أتفهّم "async"، ولكن لا أتفهّم ضبطه على "false" باستخدام JavaScript. سأنفّذ نصوصك البرمجية فور وصولها، بأي ترتيب. يعرض متصفّح Internet Explorer الذي يقلّ إصداره عن 10 ما يلي: لا نعرف أيّ معلومات عن "async"، ولكن هناك حلّ بديل باستخدام "onreadystatechange". يعرض المتصفّحات الأخرى باللون الأحمر ما يلي: لا نفهم هذا العنصر "async"، وسننفّذ نصوصك البرمجية فور وصولها، بأيّ ترتيب. تشير كل العناصر الأخرى إلى: أنا صديقك، وسننفّذ ذلك وفقًا للقواعد.