أجهزة الكمبيوتر شبابيك إنترنت

الموقتات في Javascript (setInterval ، setTimeout). أمثلة على وظيفة jQuery setTimeout () تمنع Javascript عدة مؤقتات من تشغيل setinterval في نفس الوقت

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

مثال بسيط على setTimeout

لتوضيح تأثير هذه الوظيفة ، أقترح إلقاء نظرة على العرض التوضيحي التالي ، حيث تظهر نافذة منبثقة بعد ثانيتين من النقر فوق الزر.

مشاهدة العرض

بناء الجملة

توفر وثائق MDN بناء الجملة التالي لـ setTimeout:

var timeoutID = window.setTimeout (func،) ، var timeoutID = window.setTimeout (كود ،) ،

  • timeoutID هو معرف رقمي يمكن استخدامه مع clearTimeout () لتعطيل المؤقت ؛
  • func هي الوظيفة التي سيتم تنفيذها ؛
  • الشفرة ( في بناء الجملة البديل) - سطر الكود المطلوب تنفيذه ؛
  • التأخير - مدة التأخير بالملي ثانية والتي سيتم بعدها تشغيل الوظيفة. الافتراضي هو 0.

setTimeout مقابل window.setTimeout

يستخدم بناء الجملة أعلاه window.setTimeout. لماذا ا؟

في الواقع ، فإن setTimeout و window.setTimeout هما عمليا نفس الوظيفة. الاختلاف الوحيد هو أنه في التعبير الثاني ، نستخدم طريقة setTimeout كخاصية لكائن النافذة العامة.

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

بالنسبة لهذا البرنامج التعليمي ، لا أريد العبث بعنصر النافذة ، ولكن بشكل عام يعود الأمر إليك بشأن البنية التي يجب استخدامها.

أمثلة على استخدام ملفات

قد يكون هذا اسم الوظيفة:

وظيفة تنفجر () (تنبيه ("Boom!") ؛) setTimeout (تنفجر ، 2000) ؛

المتغير الذي يشير إلى الوظيفة:

var explode = function () (alert ("Boom!") ؛) ؛ setTimeout (تنفجر ، 2000) ؛

أو وظيفة مجهولة:

setTimeout (الوظيفة () (التنبيه ("Boom!") ؛) ، 2000) ؛

  • يُنظر إلى هذا الرمز بشكل سيئ ، وبالتالي سيكون من الصعب تحديثه أو تصحيحه ؛
  • أنها تنطوي على استخدام طريقة التقييم () ، والتي يمكن أن تكون ثغرة أمنية محتملة ؛
  • هذه الطريقة أبطأ من غيرها لأنها تحتاج إلى تشغيل مترجم جافا سكريبت.

لاحظ أيضًا أننا نستخدم طريقة التنبيه لمهلة JavaScript لاختبار الكود.

تمرير المعلمات ل setTimout

في الاول ( بالإضافة إلى ذلك ، عبر المتصفح) ، نقوم بتمرير المعلمات إلى وظيفة رد الاتصال المنفذة باستخدام setTimeout.

في المثال التالي ، نستخرج ترحيبًا عشوائيًا من مصفوفة التحيات ونمررها كمعامل إلى وظيفة الترحيب () ، والتي يتم تنفيذها بواسطة setTimeout بتأخير لمدة ثانية واحدة:

وظيفة الترحيب (تحية) (console.log (تحية) ؛) وظيفة getRandom (arr) (عودة arr ؛) var تحيات = ["Hello" ، "Bonjour" ، "Guten Tag"] ، randomGreeting = getRandom (تحيات) ؛ setTimeout (الوظيفة () (الترحيب (الترحيب العشوائي) ؛) ، 1000) ؛

مشاهدة العرض

طريقة بديلة

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

بناءً على المثال السابق ، نحصل على:

setTimeout (الترحيب ، 1000 ، الترحيب العشوائي) ؛

لن تعمل هذه الطريقة في IE 9 وما بعده ، حيث تكون المعلمات التي تم تمريرها غير محددة. ولكن لحل هذه المشكلة MDN لديها بوليفيل خاص.

المشاكل ذات الصلة و "هذا"

يعمل الكود الذي ينفذه setTimeout بشكل منفصل عن الوظيفة التي يطلق عليها. لهذا السبب ، نواجه بعض المشكلات ، يمكن استخدام هذه الكلمة الأساسية كحل.

var person = (FirstName: "Jim" ، تقديم: function () (console.log ("Hi، I" m "+ this.firstName)؛))؛ person.introduce ()؛ // Outputs: Hi، I" m Jim setTimeout (person.introduce، 50) ؛ // المخرجات: مرحبًا ، أنا غير محدد

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

للتخلص من هذا التناقض ، يمكنك استخدام عدة طرق:

فرض هذا ليتم تعيينه

يمكن القيام بذلك باستخدام bind () ، وهي طريقة تنشئ وظيفة جديدة ، عندما يتم تسميتها كقيمة لهذا المفتاح ، فإنها تستخدم قيمة محددة. في حالتنا ، يعترض الشخص المحدد. هذا يعطينا نتيجة لذلك:

setTimeout (person.introduce.bind (شخص) ، 50) ؛

ملاحظة: تم تقديم طريقة الربط في ECMAScript 5 ، مما يعني أنها ستعمل فقط في المتصفحات الحديثة. في حالات أخرى ، ستحصل على خطأ وقت تشغيل عند تطبيقه جافا سكريبت "خطأ انتهاء مهلة الوظيفة".

استخدم المكتبة

تتضمن العديد من المكتبات وظائف مضمنة مطلوبة لحل هذه المشكلة. على سبيل المثال ، طريقة jQuery.proxy (). يأخذ وظيفة ويعيد وظيفة جديدة ، حيث سيستخدم دائمًا سياق معين. في حالتنا ، سيكون السياق:

setTimeout ($. proxy (person.introduce، person)، 50) ؛

مشاهدة العرض

تعطيل عداد الوقت

القيمة المرجعة لـ setTimeout هي معرف رقمي يمكن استخدامه لتعطيل المؤقت باستخدام وظيفة clearTimeout ():

var timer = setTimeout (myFunction، 3000) ؛ clearTimeout (مؤقت) ؛

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

مشاهدة المثال

دعونا نلخص

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

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

  • فار معرف = setTimeout (fn ، تأخير) ؛ - ينشئ مؤقتًا بسيطًا يستدعي الوظيفة المحددة بعد التأخير المحدد. تقوم الوظيفة بإرجاع معرف فريد يمكن من خلاله إيقاف المؤقت مؤقتًا.
  • فار معرف = setInterval (fn ، تأخير) ؛ - مشابه لـ setTimeout ، لكنه يستدعي الوظيفة باستمرار في الفاصل الزمني المحدد (حتى يتوقف).
  • clearInterval (id) ؛ ، clearTimeout (id) ؛ - يقبل معرّف عداد الوقت (يُعاد بواسطة إحدى الوظائف المذكورة أعلاه) ويوقف تنفيذ رد النداء "أ.
الفكرة الرئيسية التي يجب مراعاتها هي أن دقة فترة تأخير المؤقت غير مضمونة. بادئ ذي بدء ، ينفذ المتصفح جميع أحداث JavaScript غير المتزامنة على نفس سلسلة الرسائل (مثل نقرات الماوس أو المؤقتات) وفقط عندما يكون الحدث بدوره. يتضح هذا بشكل أفضل من خلال الرسم التخطيطي التالي:

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

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

بادئ ذي بدء ، دعنا نتخيل أن مؤقتين يبدأان داخل كتلة JavaScript: setTimeout بتأخير 10 مللي ثانية و setInterval بنفس التأخير. اعتمادًا على وقت بدء تشغيل المؤقت ، سيتم إطلاقه في الوقت الذي لم ننتهي فيه بعد من أول كتلة من الكود. لاحظ ، مع ذلك ، أنه لا يتم إطلاقه على الفور (غير ممكن بسبب الخيط المفرد). بدلاً من ذلك ، يتم وضع الوظيفة المؤجلة في قائمة الانتظار وتنفيذها في الوقت المتاح التالي.

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

بعد تنفيذ الجزء الأول من كود JavaScript ، يسأل المتصفح السؤال "ما الذي ينتظر التنفيذ؟" في هذه الحالة ، يكون معالج النقر بالماوس والمؤقت في حالة معلقة. يختار المستعرض واحدًا منهم (انقر فوق معالج) وينفذه. سينتظر الموقت الجزء الزمني المتاح التالي في قائمة انتظار التنفيذ.

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

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

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

دعنا نلقي نظرة على مثال يوضح الفرق بين setTimeout و setInterval.
setTimeout (الوظيفة () (/ * كتلة طويلة من التعليمات البرمجية ... * / setTimeout (arguments.callee، 10)؛)، 10)؛ setInterval (الوظيفة () (/ * كتلة طويلة من التعليمات البرمجية ... * /) ، 10) ؛
هذان الخياران متكافئان للوهلة الأولى ، لكنهما في الواقع ليسا كذلك. دائمًا ما يكون للكود الذي يستخدم setTimeout تأخير لا يقل عن 10 مللي ثانية بعد المكالمة السابقة (يمكن أن يكون أكثر ، لكن لا يمكن أن يكون أقل من ذلك) ، بينما سيتم استدعاء الكود الذي يستخدم setInterval كل 10 مللي ثانية بغض النظر عن وقت تنفيذ المكالمة السابقة.

دعنا نلخص ما ورد أعلاه:
- تستخدم محركات جافا سكريبت بيئة ذات ترابط واحد ، وتحول الأحداث غير المتزامنة إلى قائمة انتظار تنتظر التنفيذ ،
- يتم تنفيذ الدالتين setTimeout و setInterval بطرق مختلفة اختلافًا جوهريًا في كود غير متزامن ،
- إذا تعذر تنفيذ المؤقت في الوقت الحالي ، فسيتم تأخيره حتى نقطة التنفيذ التالية (والتي ستكون أطول من التأخير المطلوب) ،
- يمكن تنفيذ الفواصل الزمنية (setInterval) واحدة تلو الأخرى دون تأخير إذا استغرق تنفيذها وقتًا أطول من التأخير المحدد.

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

  • من عند:
  • مسجل: 2014.07.08
  • دعامات: 3,896
  • الإعجابات: 497

الموضوع: SetTimeOut و SetInterval ، أيهما أفضل للاستخدام في JavaScript؟

لتشغيل الكود عدة مرات على فترات منتظمة ، استخدم الوظيفة تعيين الفاصل الزمني... ومع ذلك ، فإن له عددًا من العيوب ، خاصة السلوك المختلف في المتصفحات المختلفة.

الاختلاف الأول هو الاختلاف عند ضبط عداد الوقت على البداية التالية. دعنا ننشئ اختبارًا صغيرًا: سنقيس مقدار الوقت المنقضي من بداية التشغيل السابق ومن نهايته.

var d1 = تاريخ جديد () ، d2 = تاريخ جديد () ؛ setInterval (function () (var d = new Date () ؛ document.body.innerHTML + = (d - d1) + "" + (d - d2) + "
"؛ // ضع تسمية في بداية الوظيفة d1 = new Date () ؛ بينما (new Date () - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

سيكون الإخراج مفيدًا بدءًا من السطر الثاني.

سيكون الوضع مشابهًا في Firefox و Opera و Safari و Chrome: سيكون الرقم الأول مساويًا تقريبًا لـ 1000 ، والثاني - 200 أقل. سيكون الاختلاف فقط في نطاق القيم. أصغر اختلاف في Chrome و Opera.

2 الرد من قبل PunBB (تحرير PunBB 2017.06.08 16:45)

  • من عند: موسكو ، Sovkhoznay 3 ، شقة. 98
  • مسجل: 2014.07.08
  • دعامات: 3,896
  • الإعجابات: 497

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

setInterval (function () (document.body.innerHTML = Math.random () ؛) ، 500) ؛

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

عيب صغير آخر لوظيفة setInterval هو أنه لكي تتمكن من إيقاف عملها ، عليك أن تتذكر معرفها في مكان ما ، وهو أمر غير مناسب دائمًا.

3 الرد من قبل PunBB

  • من عند: موسكو ، Sovkhoznay 3 ، شقة. 98
  • مسجل: 2014.07.08
  • دعامات: 3,896
  • الإعجابات: 497

إعادة: SetTimeOut و SetInterval ، أيهما أفضل للاستخدام في JavaScript؟

للتخلص من عيوب setInterval المدرجة ، يمكنك استخدام عدة setTimeout.

بديل مهم لـ setInterval هو تعيين متكرر مهلة:

/ ** بدلاً من: var timerId = setInterval (function () (alert ("tick") ؛) ، 2000) ؛ * / var timerId = setTimeout (function tick () (alert ("tick") ؛ timerId = setTimeout (tick ، ​​2000) ؛) ، 2000) ؛

في الكود أعلاه ، تمت جدولة التنفيذ التالي مباشرة بعد التنفيذ السابق.

العودية setTimeout هي طريقة توقيت أكثر مرونة من setInterval ، حيث يمكن جدولة الوقت حتى التنفيذ التالي بشكل مختلف ، اعتمادًا على نتائج التنفيذ الحالي.

على سبيل المثال ، لدينا خدمة تستقصي الخادم عن البيانات الجديدة كل 5 ثوانٍ. إذا كان الخادم محملاً بشكل زائد ، يمكنك زيادة الفاصل الزمني للاستقصاء إلى 10 ، 20 ، 60 ثانية ... ثم إعادته مرة أخرى عندما يتم تطبيع كل شيء.

إذا كانت لدينا مهام تقوم بتحميل المعالج بانتظام ، فيمكننا تقدير الوقت المستغرق في تنفيذها وتحديد موعد الإطلاق التالي عاجلاً أم آجلاً.

4 الرد من قبل PunBB

  • من عند: موسكو ، Sovkhoznay 3 ، شقة. 98
  • مسجل: 2014.07.08
  • دعامات: 3,896
  • الإعجابات: 497

إعادة: SetTimeOut و SetInterval ، أيهما أفضل للاستخدام في JavaScript؟

يضمن setTimeout العودية توقفًا مؤقتًا بين المكالمات ، بينما لا يقوم setInterval بذلك.

دعونا نقارن بين الرمزين. يستخدم الأول setInterval:

var i = 1 ؛ setInterval (الوظيفة () (func (i) ؛) ، 100) ؛

الثاني يستخدم setTimeout العودية:

var i = 1 ؛ setTimeout (تشغيل الوظيفة () (func (i) ؛ setTimeout (تشغيل ، 100) ؛) ، 100) ؛

باستخدام setInterval ، سيطلق المؤقت الداخلي كل 100 مللي ثانية بالضبط ويستدعى func (i):

التوقف الحقيقي بين مكالمات func مع setInterval أقل مما هو محدد في الكود!

هذا أمر طبيعي ، لأن وقت تشغيل الوظيفة لا يؤخذ في الاعتبار بأي شكل من الأشكال ، فهو "يأكل" جزءًا من الفترة الزمنية.

من الممكن أيضًا أن تكون وظيفة func أكثر تعقيدًا مما توقعنا واستغرق تنفيذها أكثر من 100 مللي ثانية.

في هذه الحالة ، سينتظر المترجم الفوري حتى تكتمل الوظيفة ، ثم يتحقق من المؤقت ، وإذا كان وقت استدعاء setInterval قد حان بالفعل (أو انقضى) ، فستحدث المكالمة التالية على الفور.

إذا استغرقت الوظيفة وقتًا أطول من فترة الإيقاف المؤقت setInterval ، فستحدث المكالمات دون انقطاع على الإطلاق.

5 الرد من قبل سيمباي

  • من عند: بيت المقدس
  • مسجل: 2015.06.02
  • دعامات: 958
  • الإعجابات: 274

إعادة: SetTimeOut و SetInterval ، أيهما أفضل للاستخدام في JavaScript؟

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

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

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

المصدر: http://learn.javascript.ru/settimeout-setinterval

تحتوي جميع تطبيقات JavaScript تقريبًا على مؤقت جدولة داخلي يسمح لك بجدولة استدعاء وظيفة بعد فترة زمنية محددة.

على وجه الخصوص ، يتم دعم هذه الميزة في المتصفحات وفي خادم Node.JS.

setTimeout

بناء الجملة:

var timerId = setTimeout (func / code، delay [، arg1، arg2 ...])

خيارات:

  • func / كود
    • وظيفة أو سطر من التعليمات البرمجية ليتم تنفيذها.
    • السلسلة مدعومة من أجل التوافق ولا يوصى بها.
  • تأخير
    • التأخير بالملي ثانية ، 1000 ميلي ثانية تساوي ثانية واحدة.
  • arg1، arg2 ...
    • الحجج لتمرير الوظيفة. غير مدعوم في IE9-.
    • سيتم تنفيذ الوظيفة بعد الوقت المحدد في معامل التأخير.

على سبيل المثال ، سوف يقوم الكود التالي باستدعاء تنبيه ("مرحبًا") بعد ثانية واحدة:

وظيفة func ()(تنبيه ("Hello") ؛) setTimeout (func، 1000) ؛

إذا كانت الوسيطة الأولى عبارة عن سلسلة ، فإن المترجم ينشئ دالة مجهولة من تلك السلسلة.

وهذا يعني أن مثل هذا السجل يعمل بنفس الطريقة تمامًا:

SetTimeout ("تنبيه (" مرحبًا ")" ، 1000) ؛

استخدم وظائف مجهولة بدلاً من ذلك:

SetTimeout ( وظيفة ()(تنبيه ("مرحبًا")) ، 1000) ؛

معلمات الوظيفة والسياق

في جميع المتصفحات الحديثة ، مع وضع IE10 في الاعتبار ، تتيح لك setTimeout تحديد معلمات الوظيفة.

سيعرض المثال أدناه "مرحبًا ، أنا Vasya" في كل مكان باستثناء IE9-:

وظيفة تقول مرحبا (من)(تنبيه ("مرحبًا ، أنا" + who) ؛) setTimeout (sayHi ، 1000 ، "Vasya") ؛

... ومع ذلك ، في معظم الحالات نحتاج إلى دعم IE القديم ، ولا يسمح لك بتحديد الحجج. لذلك ، من أجل تمريرها ، يتم تغليف المكالمة في وظيفة مجهولة:

وظيفة تقول مرحبا (من)(تنبيه ("مرحبًا ، أنا" + who) ؛) setTimeout ( وظيفة ()(sayHi ("Vasya")) ، 1000) ؛

استدعاء من خلال setTimeout لا يمر هذا السياق.

على وجه الخصوص ، فإن استدعاء طريقة الكائن عبر setTimeout سيعمل في السياق العام. هذا يمكن أن يؤدي إلى نتائج غير صحيحة.

على سبيل المثال ، دعنا نستدعي user.sayHi () بعد ثانية واحدة:

وظيفة المستخدم (معرف) وظيفة ()(تنبيه (هذا .id) ؛) ؛ ) var user = مستخدم جديد (12345) ؛ setTimeout (user.sayHi، 1000) ؛ // متوقع 12345 ، لكن سيطبع "غير محدد"

نظرًا لأن setTimeout ستشغل وظيفة user.sayHi في السياق العام ، فلن تتمكن من الوصول إلى الكائن عبر هذا.

بمعنى آخر ، هاتان النداءان لـ setTimeout تفعلان الشيء نفسه:

// (1) سطر واحد setTimeout (user.sayHi ، 1000) ؛ // (2) نفس الشيء في سطرين var func = user.sayHi ؛ setTimeout (func ، 1000) ؛

لحسن الحظ ، يمكن أيضًا حل هذه المشكلة بسهولة عن طريق إنشاء دالة وسيطة:

وظيفة المستخدم (معرف)(هذا معرف = معرف ؛ هذا .sayHi = وظيفة ()(تنبيه (هذا .id) ؛) ؛ ) var user = مستخدم جديد (12345) ؛ setTimeout ( وظيفة ()(user.sayHi () ؛) ، 1000) ؛

يتم استخدام وظيفة المجمع لتمرير الوسائط عبر المتصفح وتخزين سياق التنفيذ.

إلغاء التنفيذ

ترجع الدالة setTimeout معرف الوقت الذي يمكن استخدامه لإلغاء إجراء.

بناء الجملة:

ClearTimeout (timerId)

في المثال التالي ، قمنا بتعيين مهلة ثم حذف (غير رأينا). نتيجة لذلك ، لم يحدث شيء.

var timerId = setTimeout ( وظيفة ()(تنبيه (1)) ، 1000) ؛ clearTimeout (timerId) ؛

تعيين الفاصل الزمني

طريقة setInterval لها صيغة مشابهة لـ setTimeout.

var timerId = setInterval (func / code، delay [، arg1، arg2 ...])

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

ClearInterval (timerId)

المثال التالي ، عند بدء التشغيل ، سيعرض رسالة كل ثانيتين حتى تضغط على زر إيقاف:

<نوع الإدخال = "زر" onclick = "clearInterval (مؤقت)" القيمة = "(! LANG: إيقاف" > !} <نصي> var i = 1 ؛ var timer = setInterval ( وظيفة ()(تنبيه (i ++)) ، 2000) ؛نصي>

انتظار المكالمات وتراكبها في setInterval

يضع استدعاء setInterval (وظيفة ، تأخير) الوظيفة التي سيتم تنفيذها بعد الفاصل الزمني المحدد. لكن هناك دقة هنا.

في الواقع ، فإن التوقف المؤقت بين المكالمات أقل من الفاصل الزمني المحدد.

على سبيل المثال ، خذ setInterval (function () (func (i ++)) ، 100). ينفذ func كل 100 مللي ثانية ، ويزيد العداد في كل مرة.

في الصورة أدناه ، الكتلة الحمراء هي وقت تنفيذ func. الوقت بين الكتلة هو الوقت بين بداية الوظيفة وهو أقل من التأخير المحدد!

أي أن المتصفح يبدأ تشغيل الوظيفة بدقة كل 100 مللي ثانية ، دون مراعاة وقت تنفيذ الوظيفة نفسها.

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

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

توضح الصورة أدناه ما يحدث لوظيفة تستغرق وقتًا طويلاً في التنفيذ.

تتم إضافة استدعاء دالة بدأ بواسطة setInterval إلى قائمة الانتظار ويحدث فورًا عندما يصبح ذلك ممكنًا:

يحدث التشغيل الثاني للدالة مباشرة بعد نهاية الأول:

لم يتم وضع التنفيذ في قائمة الانتظار أكثر من مرة.

إذا استغرق تنفيذ إحدى الوظائف وقتًا أطول من العديد من عمليات التنفيذ المجدولة ، فستظل قائمة في قائمة الانتظار مرة واحدة. لذلك ليس هناك "تراكم" لعمليات الإطلاق.

في الصورة أدناه ، يحاول setInterval تنفيذ الوظيفة في 200 مللي ثانية ويقوم بإدراج المكالمة في قائمة الانتظار. عند 300 مللي ثانية و 400 مللي ثانية ، يستيقظ المؤقت مرة أخرى ، لكن لا شيء يمر.

لا يضمن استدعاء setInterval (وظيفة ، تأخير) تأخيرًا حقيقيًا بين عمليات التنفيذ.

هناك أوقات يكون فيها التأخير الفعلي أكبر أو أقل من التأخير المحدد. بشكل عام ، ليس حقيقة أنه سيكون هناك نوع من التأخير على الأقل.

تكرار setTimeout المتداخلة

في الحالات التي لا يلزم فيها التكرار المنتظم فقط ، ولكن يلزم وجود تأخير بين عمليات البدء ، يجب تعيين setTimeout مرة أخرى في كل مرة يتم فيها تنفيذ الوظيفة.

يوجد أدناه مثال يرسل تنبيهًا بفواصل زمنية مدتها ثانيتان.

<نوع الإدخال = "زر" onclick = "clearTimeout (مؤقت)" القيمة = "(! LANG: إيقاف" > !} <نصي> var i = 1 ؛ var timer = setTimeout ( تشغيل الوظيفة ()(تنبيه (i ++) ؛ timer = setTimeout (تشغيل ، 2000) ؛) ، 2000) ؛نصي>

سيكون هناك تأخير ثابت بين عمليات التشغيل في الجدول الزمني للتنفيذ. رسم توضيحي لتأخير 100 مللي ثانية:

الحد الأدنى من تأخير الموقت

يحتوي مؤقت المتصفح على أقل زمن انتقال ممكن. وهي تختلف من صفر إلى 4 مللي ثانية في المتصفحات الحديثة. في الأقدم ، يمكن أن تكون أعلى وتصل إلى 15 مللي ثانية.

وفقًا للمعيار ، فإن الحد الأدنى للتأخير هو 4 مللي ثانية. لذلك لا فرق بين setTimeout (..، 1) و setTimeout (..، 4).

إن سلوكيات setTimeout و setInterval ذات زمن انتقال صفري خاصة بالمتصفح.

  1. في Opera ، يكون setTimeout (.. ، 0) هو نفسه setTimeout (.. ، 4). يتم تشغيله بشكل أقل من setTimeout (.. ، 2). هذه هي ميزة هذا المتصفح.
  2. في Internet Explorer ، ستفشل setInterval (..، 0) صفر تأخير. ينطبق هذا تحديدًا على setInterval ، أي setTimeout (..، 0) يعمل بشكل جيد.

تردد الاستجابة الفعلية

يمكن تشغيله بشكل أقل تكرارًا. في بعض الحالات ، قد لا يكون التأخير 4 مللي ثانية ، ولكن 30 مللي ثانية أو حتى 1000 مللي ثانية.

تستمر معظم المتصفحات (سطح المكتب في المقام الأول) في تنفيذ setTimeout / setInterval حتى إذا كانت علامة التبويب غير نشطة. في الوقت نفسه ، يعمل عدد منهم (Chrome ، FF ، IE10) على تقليل الحد الأدنى لتكرار المؤقت ، وصولاً إلى مرة واحدة في الثانية. اتضح أن جهاز ضبط الوقت سيعمل في علامة التبويب "الخلفية" ، ولكن نادرًا ما يعمل.

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

الخلاصة: يجب أن تسترشد بالتردد 4 مللي ثانية ، لكن لا يجب أن تعتمد عليه.

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

var timeMark = تاريخ جديد ؛ setTimeout ( وظيفة الذهاب ()(var diff = new Date - timeMark ؛ // طباعة تأخير آخر على وحدة التحكم بدلاً من الصفحةوحدة التحكم .log (فرق) ؛ // تذكر الوقت في النهاية ، // لقياس التأخير بالضبط بين المكالمات timeMark = تاريخ جديد ؛ setTimeout (اذهب ، 100) ؛ ) ، 100) ؛

خدعة setTimeout (func، 0)

تستحق هذه الحيلة إدخال سجلات عمليات اختراق JavaScript.

يتم تغليف الوظيفة في setTimeout (func ، 0) إذا كنت تريد تشغيلها بعد نهاية البرنامج النصي الحالي.

النقطة المهمة هي أن setTimeout لا تنفذ أبدًا وظيفة على الفور. هو فقط يخطط لتنفيذه. لكن مترجم JavaScript سيبدأ في تنفيذ الوظائف المخطط لها فقط بعد تنفيذ النص الحالي.

وفقًا للمعيار ، لا يمكن لـ setTimeout تنفيذ وظيفة بتأخير قدره 0 على أي حال. كما قلنا سابقًا ، عادةً ما يكون التأخير 4 مللي ثانية. لكن الشيء الرئيسي هنا هو أن التنفيذ في أي حال سيكون بعد تنفيذ الكود الحالي.

على سبيل المثال:

نتيجة فار تظهر النتيجة ()(تنبيه (نتيجة) ؛) setTimeout (showResult ، 0) ؛ النتيجة = 2 * 2 ؛ // سيطبع 4

المجموع

تسمح أساليب setInterval (func، delay) و setTimeout (func، delay) بتشغيل func بانتظام / مرة واحدة بعد مللي ثانية من التأخير.

كلا الأسلوبين يعيدان معرف عداد الوقت. يتم استخدامه لإيقاف التنفيذ عن طريق استدعاء clearInterval / clearTimeout.

| | setInterval | setTimeout | || ----------- | ---------- | | التوقيت | هناك مكالمة بدقة على الموقت. إذا كان المترجم الفوري مشغولاً ، تدخل مكالمة واحدة في قائمة الانتظار. لا يتم أخذ وقت تنفيذ الوظيفة في الاعتبار ، لذلك يمكن أن يكون الفاصل الزمني من نهاية تشغيل واحد إلى بداية تشغيل آخر مختلفًا. | يتم استخدام استدعاء متكرر لـ setTimeout بدلاً من setInterval حيث يلزم التوقف المؤقت بين عمليات التنفيذ. | | تأخير | الحد الأدنى من التأخير: 4 مللي ثانية. | الحد الأدنى من التأخير: 4 مللي ثانية. | | ميزات المتصفح | التأخير 0 لا يعمل في IE | في Opera ، وقت الاستجابة الصفري يعادل 4 مللي ثانية ، ويتم التعامل مع التأخيرات الأخرى بدقة ، بما في ذلك 1 مللي ثانية و 2 مللي ثانية و 3 مللي ثانية غير قياسية. |

في البرمجة بلغات البرمجة النصية ، من الضروري بشكل دوري إنشاء وقفة - لتعليق تنفيذ البرنامج لفترة ، ثم متابعة العمل. على سبيل المثال ، في البرامج النصية VBS و PHP ، يمكن استخدام الطرق التالية:

VBS: wscript.sleep 1500 (توقف لمدة 1.5 ثانية)

PHP: النوم (10) ؛ (توقف لمدة 10 ثوان)

أثناء فترات التوقف هذه ، فإن نظام التشغيل (PHP أو VBS) لا أفعل شئ... سوف يفاجأ المطور الذي يحاول استخدام شيء مثل هذا بشكل بديهي في جافا سكريبت. يبدو الخطأ المعتاد عند محاولة إنشاء وقفة في Javascript على النحو التالي:

دالة badtest () (لـ (var i = 1 ؛ i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

هل تعتقد أنه عند المرور عبر الحلقة ، فإن الأمر يتعلق برسم الرقم التالي ، الخاص بك setTimeoutبصراحة سيوقف عمل Javascript ، انتظر 0.9 ثانية ، أضف الرقم المطلوب إلى نهاية حقل الإدخال ، ثم تابع العمل. لكنها في الواقع ليست كذلك: تعيين الفاصل الزمنيو setTimeoutفي Javascript ، يتم تأخير الإجراء (أو الوظيفة) المشار إليها بين قوسين فقط. في مثالنا ، سيحدث ما يلي:

  1. أنا = 1 ؛
  2. تأجيل إضافة الرقم "1" إلى حقل الإدخال بمقدار 0.9 ثانية ؛
  3. فورابعد تحديد هذه المشكلة ، تستمر الدورة: i = 2 ؛
  4. تأجيل إضافة الرقم "2" إلى حقل الإدخال بمقدار 0.9 ثانية ؛

فورايعني ، على سبيل المثال ، 1 مللي ثانية (أي صغير بشكل غير قابل للقياس ، مقارنة بـ 900 مللي ثانية): ستؤدي الدورة عملها على الفور تقريبًا ، مما يؤدي إلى إنشاء العديد من المهام المعلقة من نفس النقطة الزمنية. هذا يعني أن جميع مهام "الرسم" المعلقة ستكتمل في نفس الوقت تقريبًا ، دون توقف مؤقت بين إضافة أرقام جديدة. تبدأ الدورة ؛ كل شيء يتجمد لمدة 0.9 ثانية ؛ و shirrr - يتم تصوير جميع الأرقام واحدة تلو الأخرى.

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

اختبار الأداء الوظيفي () (إذا (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

ومتغير آخر أنايجب أن تتم تهيئته خارج الوظيفة - على سبيل المثال ، مثل هذا:

الآن كل شيء يعمل كما ينبغي (قللنا وقت التأخير من 0.9 ثانية إلى 0.4 ثانية). لكن بالنسبة لمثل هذه المهام ، من المنطقي ألا تستخدم setTimeoutأ تعيين الفاصل الزمني(على الرغم من أن هذا قد يتطلب وظيفتين):

الوظيفة besttest () (window.i = 0 window.timer1 = window.setInterval ("draw ()"، 400)) وظيفة الرسم () (document.getElementById ("test3"). القيمة + = ++ i if (i > = 9) clearInterval (window.timer1))

سمة من سمات طريقة Javascirpt تعيين الفاصل الزمنيحقيقة أنه لا يمر "من تلقاء نفسه" ، يجب إيقافه بطريقة خاصة واضح... ولتوضيح ما يجب إيقافه ، يتم تعيين معرّف خاص لمهمة الإجراء المؤجل - مؤقت: window.timer1 = window.setInterval (...).

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

فيما يلي مثال لصفحة بها عدة مؤقتات Javascript تعمل في نفس الوقت: setinterval.htm (وظائف Javascript في ملف setinterval.js). يمكن إيقاف تشغيل جميع مؤقتات الصفحات (باستثناء القائمة) بالضغط على مفتاح Esc. تعتمد جميع أمثلة الموقتات على "طبيعي" (وليس مجرد أنا ++) العد التنازلي - الوقت أو المسافة. جميع "الساعات" غير متزامنة بشكل خاص (من أجل الوضوح). يتم استخدام أجهزة ضبط الوقت على أساس المسافة في "المؤشر" وفي القائمة المنسدلة (المنسدلة).

القائمة المنسدلة

قائمة السحب الخاصة بنا مسحوبة فعليًا (من أسفل "العنوان"): توجد فجوات بين العناصر لمعرفة كيفية انسحابها. بشكل غير متوقع ، اتضح أنه لا يمكننا إجراء خروج سلس بنفس القدر لقوائم ذات أطوال مختلفة - ربما بسبب الأداء المنخفض للكمبيوتر (AMD Athlon 999 MHz).

من الواضح تمامًا أنه من أجل الجمال والانسجام ، من الضروري أن تظهر قوائم بعناصر القائمة المختلفة في نفس الوقت. وهذا يعني أن القوائم الأطول يجب أن تنسحب بمعدل أسرع ، والقوائم الأقصر - بمعدل أقل. يبدو أنه يمكن تنفيذه على النحو التالي:

  1. حددنا الوقت الإجمالي "للمغادرة" ، على سبيل المثال ، بـ 200 مللي ثانية.
  2. إذا كان ارتفاع القائمة المنسدلة 20 بكسل ، فمن الواضح أنه يمكننا نقلها لأسفل بمقدار بكسل واحد في وقت 10 مللي ثانية - وبعد ذلك في 200 مللي ثانية ، سيتم الزحف إلى القائمة بأكملها.
  3. إذا كانت القائمة المنسدلة عالية 40 بكسل ، لتلائم في نفس الوقت ، يتعين علينا نقلها لأسفل بمقدار بكسل واحد في كل مرة في 5 مللي ثانية.

وفقًا لهذا المنطق ، إذا كانت القائمة المنسدلة بارتفاع 200 بكسل ، فيجب علينا تحريكها لأسفل بمقدار بكسل واحد في كل مرة خلال 1 مللي ثانية. لكن هذه السرعة لا تعمل على جهاز الكمبيوتر الخاص بنا - فالمتصفح ببساطة لا يملك الوقت لرسم الموضع الجديد من القائمة في جزء من الثانية. نعم فعلا. جافا سكريبت لديها الوقت للعد (ما الذي يمكن حسابه؟) ، لكن متصفح (فايرفوكس) ليس لديه الوقت لعرضه. وضع نموذجي للويب.

لذلك ، من الممكن معادلة وقت مغادرة القائمة بشكل أو بآخر بمساعدة العكازات ، ولا يزال من غير الواضح كيف سيعمل ذلك على جهاز كمبيوتر أسرع. لكن يجب أن نعتمد على الأبطأ ، أليس كذلك؟ تبين أن الخوارزمية (دون مراعاة سرعة الكمبيوتر) هي شيء من هذا القبيل:

  1. حددنا إجمالي وقت الخروج من القائمة: الوقت = 224 (مللي ثانية).
  2. قمنا بتعيين الحد الأدنى من الوقت لفترة واحدة في الدورة: التأخير = 3 (مللي ثانية).
  3. عيّن الخطوة الدنيا لنقل القائمة: offset = 1 (px).
  4. نغير كل هذا اعتمادًا على ارتفاع القائمة: 1) نزيد وقت التأخير (الفاصل الزمني) بالتناسب العكسي مع الارتفاع وبالتناسب المباشر مع الوقت الإجمالي (على ارتفاع 224 ، يكون المعامل 1) ؛ 2) إذا كان الارتفاع أكثر من 40 بكسل ، فقم بزيادة الحد الأدنى للخطوة بما يتناسب مع الارتفاع. يتم الحصول على الثابت "40" تجريبياً لأبطأ جهاز كمبيوتر. كشفت الاختبارات التي أجريت على جهاز كمبيوتر Pentium 4 CPU 2.53 جيجاهرتز عن نفس الرقم بالضبط - 40. وإلا ، فإن أجهزة ضبط الوقت تصبح جامحة ، والقوائم لا تواكب ذلك.

الآن يتم طرح القوائم بشكل أو بآخر. لوقت مماثل إلى حد ما. في صفحة setinterval.htm.

وهنا برو شارب:

الوظيفة slide_do (obj، maxtop، offset) (if (getTopLeft (obj) .top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

الوظيفة نفسها ، التي تُخرج القوائم المتداخلة من القائمة ، كما ترى ، بسيطة للغاية. يبقى فقط لتشغيله بشيء مثل هذا الخط:

Ts.timer1 = setInterval (الوظيفة () (slide_do (ts ، maxtop ، offset)) ، تأخير)

حسنًا ، قبل البدء ، ما عليك سوى حساب كل هذه القيم القصوى والإزاحة ، وكذلك ضع القائمة في موضع mintop. ما الذي تفعله الوظيفة "التمهيدية" الانزلاق ()حجم 40 سطرًا. وكل ذلك معًا - في ملف setinterval.js. نعم ، ولن تعمل هذه الحماقة بدون ورقة أنماط مضمنة.