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

كرر الإجراءات في فترة زمنية محددة لجافا سكريبت. أمثلة على دالة jQuery setTimeout(). setTimeout مع تأخير صفر

  • من:
  • مسجل: 2014.07.08
  • المشاركات: 3,896
  • الإعجابات: 497
الموضوع: SetTimeOut وSetInterval، أيهما أفضل للاستخدام في JavaScript؟

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

الاختلاف الأول هو الفرق في الوقت الذي يتم فيه ضبط المؤقت للإطلاق التالي. لنقم بإنشاء اختبار صغير: سنقيس مقدار الوقت الذي انقضى منذ بداية الجولة السابقة ومنذ نهايتها.

var d1 = new Date(), d2 = new Date(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // ضع علامة في بداية الدالة d1 = new Date(); while (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)
  • من: موسكو، سوفخوزناي 3، شقة. 98
  • مسجل: 2014.07.08
  • المشاركات: 3,896
  • الإعجابات: 497

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

setInterval(function() ( document.body.innerHTML = Math.random(); ), 500);

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

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

3 الرد بواسطة PunBB
  • من: موسكو، سوفخوزناي 3، شقة. 98
  • مسجل: 2014.07.08
  • المشاركات: 3,896
  • الإعجابات: 497
رد: SetTimeOut وSetInterval، أيهما أفضل للاستخدام في JavaScript؟

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

البديل المهم لـ setInterval هو setTimeout العودي:

/** بدلاً من: var timerId = setInterval(function() ( تنبيه("tick"); , 2000); */ var timerId = setTimeout(function Tick() ( تنبيه("tick"); timerId = setTimeout(tick, 2000); ), 2000);

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

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

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

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

4 الرد بواسطة PunBB
  • من: موسكو، سوفخوزناي 3، شقة. 98
  • مسجل: 2014.07.08
  • المشاركات: 3,896
  • الإعجابات: 497
رد: SetTimeOut وSetInterval، أيهما أفضل للاستخدام في JavaScript؟

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

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

فار ط = 1؛ setInterval(function() ( func(i); ), 100);

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

فار ط = 1؛ setTimeout(function run() ( func(i); setTimeout(run, 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 في الوقت الحالي هو أنه لا يأخذ في الاعتبار وقت تنفيذ البرنامج النصي (الوظيفة) نفسه، وإذا كنت، على سبيل المثال، تستخدمه للاستعلامات الثقيلة، فسيتم تقليل وقت الفاصل الزمني بشكل كبير، وهو قد تختلف في متصفحات مختلفة.

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

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

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

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

عرض العرض التوضيحي

بناء الجملة

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

فار timeoutID = window.setTimeout(func, ); فار timeoutID = window.setTimeout(code, );

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

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

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

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

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

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

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

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

المتغير الذي يشير إلى الدالة:

فار تنفجر = وظيفة())( تنبيه("بوم!"); ); setTimeout(explode, 2000);

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

setTimeout(function())( تنبيه("Boom!"); ), 2000);

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

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

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

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

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

وظيفة تحية(ترحيب)( console.log(greeting); ) وظيفة getRandom(arr)( return arr; ) var Greetings = ["Hello", "Bonjour", "Guten Tag"], RandomGreeting = getRandom(greetings); setTimeout(function())(greet(randomGreeting); ), 1000);

عرض العرض التوضيحي

طريقة بديلة

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

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

setTimeout(greet, 1000, RandomGreeting);

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

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

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

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

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

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

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

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

setTimeout(person.introduce.bind(person), 50);

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

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

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

setTimeout($.proxy(person.introduce, person), 50);

عرض العرض التوضيحي

تعطيل الموقت

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

var timer = setTimeout(myFunction, 3000); ClearTimeout(timer);

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

عرض المثال

دعونا نلخص ذلك

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

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

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

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

setTimeout

بناء الجملة:

فار timerId = setTimeout(func/code, Delay[, arg1, arg2...])

خيارات:

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

على سبيل المثال، الكود التالي سيطلق التنبيه ("Hello") بعد ثانية واحدة:

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

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

أي أن هذا الإدخال يعمل بنفس الطريقة تمامًا:

SetTimeout("alert("Hello")" , 1000 );

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

SetTimeout(function () ( تنبيه("Hello") ), 1000 );

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

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

سيعرض المثال أدناه "Hello, I'm Vasya" في كل مكان باستثناء IE9-:

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

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

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

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

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

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

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

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

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

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

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

وظيفة المستخدم (المعرف) ( this .id = id; this .sayHi = function () ( تنبيه(this .id); ); ) var user = new User(12345); setTimeout(function () ( user.sayHi(); ), 1000);

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

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

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

بناء الجملة:

ClearTimeout(معرف المؤقت)

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

var timerId = setTimeout(function () ( تنبيه(1) ), 1000 ); ClearTimeout(timerId); setInterval

يحتوي أسلوب setInterval على بناء جملة مشابه لـ setTimeout.

فار timerId = setInterval(func/code, Delay[, arg1, arg2...])

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

كلير إنترفال (معرف المؤقت)

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

فار ط = 1 ; var timer = setInterval(function () ( تنبيه(i++) ), 2000 ); قائمة الانتظار وتراكب المكالمات في setInterval

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

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

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

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

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

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

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

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

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

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

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

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

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

استدعاء setInterval(function, Delay) لا يضمن التأخير الفعلي بين عمليات التنفيذ.

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

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

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

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

فار ط = 1 ; var timer = setTimeout(function run () (alert(i++); timer = setTimeout(run, 2000 ); ), 2000);

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

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

يتميز مؤقت المتصفح بأقل زمن وصول ممكن. ويتراوح من صفر إلى 4 مللي ثانية تقريبًا في المتصفحات الحديثة. في الأكبر سنا يمكن أن يكون أطول ويصل إلى 15 مللي ثانية.

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

سلوك زمن الوصول الصفري لـ setTimeout وsetInterval خاص بالمتصفح.

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

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

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

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

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

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

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

    هذه الخدعة تستحق أن تدخل في سجلات اختراق جافا سكريبت.

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

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

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

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

    نتيجة فار؛ دالة showResult () ( تنبيه(نتيجة); ) setTimeout(showResult, 0 ); النتيجة = 2 *2 ; // سوف يخرج 4 المجموع

    تتيح لك الطرق setInterval(func, Delay) وsetTimeout(func, Delay) تشغيل func بانتظام/مرة واحدة كل تأخير بالمللي ثانية.

    تقوم كلتا الطريقتين بإرجاع معرف المؤقت. يتم استخدامه لإيقاف التنفيذ عن طريق استدعاء ClearInterval / ClearTimeout .

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

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

    بناء الجملة معرف الفاصل الزمني فار = نِطَاق.setInterval( func, تأخير, [arg1, arg2, ...]); معرف الفاصل الزمني فار = نِطَاق.setInterval( شفرة, تأخير); المعلمات func دالة يتم تنفيذها كل مللي ثانية تأخير. لم يتم تمرير الدالة أية وسائط، ومن المتوقع عدم وجود قيمة إرجاع. رمز يسمح لك بناء الجملة الاختياري بتضمين سلسلة بدلاً من وظيفة، والتي يتم تجميعها وتنفيذها في كل مللي ثانية تأخير. بناء الجملة هذا هو لا ينصحلنفس الأسباب التي تجعل استخدام eval() خطرًا أمنيًا. تأخير الوقت، بالمللي ثانية (ألف من الثانية)، يجب أن يتأخر المؤقت بين عمليات تنفيذ الوظيفة أو الكود المحدد. انظر أدناه للحصول على تفاصيل حول النطاق المسموح به لقيم التأخير. arg1, ..., argN وسيطات إضافية اختيارية يتم تمريرها إلى الوظيفة المحددة بواسطة funcبمجرد انتهاء الموقت.

    ملاحظة: تمرير وسائط إضافية إلى setInterval() في الصيغة الأولى لا يعمل في Internet Explorer 9 والإصدارات الأقدم. إذا كنت تريد تمكين هذه الوظيفة على هذا المتصفح، فيجب عليك استخدام polyfill (راجع القسم).

    قيمة الإرجاع

    معرف الفاصل الزمني الذي تم إرجاعه هو قيمة رقمية غير صفرية تحدد المؤقت الذي تم إنشاؤه بواسطة استدعاء setInterval() ؛ يمكن تمرير هذه القيمة لإلغاء المهلة.

    قد يكون من المفيد أن تكون على علم بأن setInterval() وsetTimeout() يشتركان في نفس مجموعة المعرفات، وأنه يمكن استخدام ClearInterval() وclearTimeout() تقنيًا بالتبادل. ومع ذلك، من أجل الوضوح، يجب أن تحاول مطابقتها دائمًا لتجنب الارتباك عند الحفاظ على التعليمات البرمجية الخاصة بك.

    ملاحظة: يتم تحويل وسيطة التأخير إلى عدد صحيح 32 بت. وهذا يحد بشكل فعال من التأخير إلى 2147483647 مللي ثانية، حيث تم تحديده كعدد صحيح موقّع في IDL.

    أمثلة المثال 1: بناء الجملة الأساسي

    يوضح المثال التالي بناء جملة setInterval() الأساسي.

    var IntervalID = window.setInterval(myCallback, 500, "Parameter 1", "Parameter 2"); وظيفة myCallback(a, b) ( // الكود الخاص بك هنا // المعلمات اختيارية تمامًا. console.log(a); console.log(b); )

    مثال 2: تبديل لونين

    المثال التالي يستدعي الدالة flashtext() مرة كل ثانية حتى يتم الضغط على الزر Stop.

    مثال setInterval/clearInterval var nIntervId; الدالة ChangeColor() ( nIntervId = setInterval(flashText, 1000); ) الدالة flashText() ( var oElem = document.getElementById("my_box"); oElem.style.color = oElem.style.color == "red" ? " blue" : "red"; // oElem.style.color == "red" ? "blue" : "red" هو عامل تشغيل ثلاثي. ) وظيفة stopTextColor() ( ClearInterval(nIntervId); )

    مرحبا بالعالم

    قف

    مثال 3: محاكاة الآلة الكاتبة

    يحاكي المثال التالي الآلة الكاتبة عن طريق مسح المحتوى أولاً ثم كتابته ببطء في NodeList الذي يطابق مجموعة محددة من المحددات.

    آلة كاتبة جافا سكريبت - نموذج MDN لوظيفة الآلة الكاتبة (sSelector، nRate) ( وظيفة نظيفة () ( ClearInterval (nIntervId)؛ bTyping = false؛ bStart = true؛ oCurrent = null؛ aSheets.length = nIdx = 0؛ ) وظيفة التمرير (oSheet، nPos) , bEraseAndStop) ( إذا (!oSheet.hasOwnProperty("parts") || aMap.length< nPos) { return true; } var oRel, bExit = false; if (aMap.length === nPos) { aMap.push(0); } while (aMap < oSheet.parts.length) { oRel = oSheet.parts]; scroll(oRel, nPos + 1, bEraseAndStop) ? aMap++ : bExit = true; if (bEraseAndStop && (oRel.ref.nodeType - 1 | 1) === 3 && oRel.ref.nodeValue) { bExit = true; oCurrent = oRel.ref; sPart = oCurrent.nodeValue; oCurrent.nodeValue = ""; } oSheet.ref.appendChild(oRel.ref); if (bExit) { return false; } } aMap.length--; return true; } function typewrite () { if (sPart.length === 0 && scroll(aSheets, 0, true) && nIdx++ === aSheets.length - 1) { clean(); return; } oCurrent.nodeValue += sPart.charAt(0); sPart = sPart.slice(1); } function Sheet (oNode) { this.ref = oNode; if (!oNode.hasChildNodes()) { return; } this.parts = Array.prototype.slice.call(oNode.childNodes); for (var nChild = 0; nChild < this.parts.length; nChild++) { oNode.removeChild(this.parts); this.parts = new Sheet(this.parts); } } var nIntervId, oCurrent = null, bTyping = false, bStart = true, nIdx = 0, sPart = "", aSheets = , aMap = ; this.rate = nRate || 100; this.play = function () { if (bTyping) { return; } if (bStart) { var aItems = document.querySelectorAll(sSelector); if (aItems.length === 0) { return; } for (var nItem = 0; nItem < aItems.length; nItem++) { aSheets.push(new Sheet(aItems)); /* Uncomment the following line if you have previously hidden your elements via CSS: */ // aItems.style.visibility = "visible"; } bStart = false; } nIntervId = setInterval(typewrite, this.rate); bTyping = true; }; this.pause = function () { clearInterval(nIntervId); bTyping = false; }; this.terminate = function () { oCurrent.nodeValue += sPart; sPart = ""; for (nIdx; nIdx < aSheets.length; scroll(aSheets, 0, false)); clean(); }; } /* usage: */ var oTWExample1 = new Typewriter(/* elements: */ "#article, h1, #info, #copyleft", /* frame rate (optional): */ 15); /* default frame rate is 100: */ var oTWExample2 = new Typewriter("#controls"); /* you can also change the frame rate value modifying the "rate" property; for example: */ // oTWExample2.rate = 150; onload = function () { oTWExample1.play(); oTWExample2.play(); }; span.intLink, a, a:visited { cursor: pointer; color: #000000; text-decoration: underline; } #info { width: 180px; height: 150px; float: right; background-color: #eeeeff; padding: 4px; overflow: auto; font-size: 12px; margin: 4px; border-radius: 5px; /* visibility: hidden; */ }

    CopyLeft 2012 من شبكة مطوري موزيلا

    [ تشغيل | وقفة | إنهاء]

    Vivamus blandit Massa ut metus mattis in fringilla lectus impdiet. Proin ac ante a felis ornare vehicula. فوسس pellentesque lacus vitae eros convallis ut mollis magna pellentesque. حشرة فطرية في منطقة ultricies vitae facilisis nisi fringilla. في تينسيدونت تينسيدونت تينسيدونت. آلة كاتبة جافا سكريبت

    لوريم إيبسوم دولور سيت أميت، consectetur adipiscing إيليت. Nullam ultrices dolor ac dolor impdiet ullamcorper. Suspendisse quam libero، luctus auctor mollis sed، Malesuada condimentum magna. Quisque in ante Tellus, in placerat est. سكان فطريون مصابون بمرض ثلاثي السن وشبكة وذكور مشهورون برائحة turpis egestas. Donec a mi magna، quis mattis dolor. Etiam sit amet ligula quis urna auctor impdiet nec faucibus ante. موريس فيل كونسيكتور دولور. لا داعي للقلق بشأن هذا الأمر. Curabitur convallis، justo posuere porta egestas، velit erat ornare tortor، not viverra justo diam eget arcu. Phasellus adipiscing Fermentum nibh ac commodo. Nam turpis nunc, suscipit a hendrerit vitae, volutpat Non ipsum.

    فاسيلوس أس نيسل لوريم:
    لا داعي للقلق بشأن عدم تناول الطعام. Phasellus ac nisl lorem، sed facilisis ligula. نام cursus lobortis placerat. Sed dui nisi, elementum eu صودالز ac, placerat الجلوس أميت موريس. تخبرنا البيانات الرائعة عن نفس المنتج من قبل مالك السيارة. Quisque ultrices laoreet عصر، في ultrices tortor صوداليس غير. Sed venenatis luctus magna، ultricies ultricies nunc fringilla eget. توجد سيرة ذاتية متدرجة الشكل Nibh Tristique varius Consequat Neque Luctus. عدد صحيح ornare، erat a porta tempus، velit justo vermentum elit، a تخمير metus nisi eu ipsum. Vivamus eget augue vel dui viverra adipiscing congue ut Massa. السيرة الذاتية الحالية إيروس إيرت، بولفينار لوريت ماجنا. Maecenas الدهليزي (mollis nunc) في الوضعية. يجلس بيلينتسك ميتوس وتوربيس لوبورتيس تيمبور إي فيل تورتور. Cras Sodales eleifend Interdum.

    Duis lobortis sapien quis nisl luctus porttitor. In tempor semper libero، eu tincidunt dolor eleifend sit amet. Ut nec velit in dolor tincidunt rhoncus Non Non diam. Morbi auctor ornare orci، غير euismod felis gravida nec. لا يوجد عنصر Curabitur في أي نوع من الأشياء اللطيفة التي لا يمكن وضعها في موضع آخر. Aenean tincidunt risus ut nisi consectetur cursus. سيرتك الذاتية كإيليت. تم إنشاء الكرامة في إطار زمني محدد. Aliquam aliquam diam not felis convallis suscipit. لا يوجد تسهيلات. Donec lacus risus، dignissim et fringilla et، egestas vel eros. Duis mensuada Accumsan dui، at fringilla mauris bibStartum quis. تخمير الخميرة. برايسينت بيبستارتوم بهار فيوجيات.

    Nam faucibus، ligula eu fringilla pulvinar، lectus Tellus iaculis nunc، vitae scelerisque metus leo not metus. بروين ماتيس لوبورتيس لوبورتيس. لقد حدث هذا الأمر، والعديد من المعذبات الشديدة التيار المتردد. لوريم إيبسوم دولور سيت أميت، consectetur adipiscing إيليت. سيد غير المصنّفة ليبيرو نونك. لا يوجد أي ضرر، عنصر في التركيب والتركيب، ultrices في العالم. لوريم إيبسوم دولور سيت أميت، consectetur adipiscing إيليت. رائعة لجميع المركبات الفاخرة.

    وسيطات رد الاتصال

    كما ناقشنا سابقًا، لا يدعم الإصدار 9 والإصدارات الأقدم من Internet Explorer تمرير الوسائط إلى وظيفة رد الاتصال في setTimeout() أو setInterval() . يوضح التعليمة البرمجية الخاصة بـ IE التالية طريقة للتغلب على هذا القيد. للاستخدام، ما عليك سوى إضافة الكود التالي إلى الجزء العلوي من البرنامج النصي الخاص بك.

    /*\ |*| |*| polyfill الخاص بـ IE والذي يتيح مرور الوسائط العشوائية إلى |*| وظائف رد الاتصال لمؤقتات جافا سكريبت (بناء جملة HTML5 القياسي)..setInterval |*| https://site/User:fusionchess |*| |*| بناء الجملة: |*| var timeoutID = window.setTimeout(func, Delay[, arg1, arg2, ...]); |*| فار timeoutID = window.setTimeout(code, Delay); |*| فار الفاصل الزمني = window.setInterval(func, Delay[, arg1, arg2, ...]); |*| فار الفاصل الزمني = window.setInterval(code, Delay); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = function (vCallback, nDelay /*, الوسيطةToPass1, الوسيطةToPass2, إلخ. */) ( var aArgs = Array .prototype.slice.call(arguments, 2); return __nativeST__(مثيل vCallback للوظيفة ? الوظيفة () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay); ); window.setTimeout.isPolyfill = true; ) if (document.all && !window.setInterval.isPolyfill) ( var __nativeSI__ = window.setInterval; window.setInterval = function (vCallback, nDelay /*, الوسيطة ToPass1, الوسيطةToPass2, إلخ. */) ( var aArgs = Array.prototype. شريحة.call(arguments, 2); return __nativeSI__(مثيل vCallback للوظيفة ? الوظيفة () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay); ); window.setInterval.isPolyfill = true; )

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

    var IntervalID = setInterval(function() ( myFunc("one", "two", "three"); ), 1000); فار الفاصل الزمني = setInterval(function(arg1) ().bind(undef, 10), 1000);

    علامات التبويب غير النشطة تتطلب Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

    بدءًا من Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)، يتم تقييد الفواصل الزمنية لتشغيلها بما لا يزيد عن مرة واحدة في الثانية في علامات التبويب غير النشطة.

    مشكلة "هذه".

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

    توضيح

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

    MyArray = ["صفر"، "واحد"، "اثنان"]؛ myArray.myMethod = function (sProperty) ( تنبيه (arguments. length > 0 ? this : this); ); myArray.myMethod(); // يطبع "صفر، واحد، اثنان" myArray.myMethod(1); // طباعة "واحد" setTimeout(myArray.myMethod, 1000); // يطبع "" بعد ثانية واحدة setTimeout(myArray.myMethod, 1500, "1"); // طباعة "غير محدد" بعد 1.5 ثانية // تمرير الكائن "هذا" مع .call لن ينجح // لأن هذا سيغير قيمة هذا داخل setTimeout نفسه // بينما نريد تغيير قيمة هذا داخل myArray .myMethod // في الواقع، سيكون خطأً لأن كود setTimeout يتوقع أن يكون هذا هو كائن النافذة: setTimeout.call(myArray, myArray.myMethod, 2000); // خطأ: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: عملية غير قانونية على كائن النموذج الأولي WrappedNative" setTimeout.call(myArray, myArray.myMethod, 2500, 2); // نفس الخطأ

    كما ترون، لا توجد طرق لتمرير هذا الكائن إلى وظيفة رد الاتصال في JavaScript القديمة.

    حل ممكن

    إحدى الطرق الممكنة لحل مشكلة "هذه" هي استبدال الدالتين العموميتين الأصليتين setTimeout() أو setInterval() بوظيفتين غير أصليتلك التي تمكن استدعائها من خلال طريقة Function.prototype.call. يوضح المثال التالي بديلاً محتملاً:

    // تمكين مرور الكائن "هذا" من خلال مؤقتات JavaScript var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = وظيفة (vCallback، nDelay /*، الوسيطة ToPass1، الوسيطةToPass2، إلخ. */) ( var oThis = this، aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(مثيل vCallback للوظيفة ? وظيفة () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay); ); window.setInterval = وظيفة (vCallback، nDelay /*، الوسيطة ToPass1، الوسيطةToPass2، إلخ. */) ( var oThis = this، aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(مثيل vCallback للوظيفة ? وظيفة () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay); );

    يعمل هذان البديلان أيضًا على تمكين المرور القياسي لـ HTML5 للوسائط العشوائية إلى وظائف رد الاتصال للمؤقتات في IE. لذلك يمكن استخدامها ك غير متوافق مع المعايير polyfills أيضا. انظر ل متوافقة مع المعايير polyfill

    اختبار الميزة الجديدة:

    MyArray = ["صفر"، "واحد"، "اثنان"]؛ myArray.myMethod = function (sProperty) ( تنبيه (arguments. length > 0 ? this : this); ); setTimeout(alert, 1500, "Hello World!"); // يتم الحفاظ على الاستخدام القياسي لـ setTimeout وsetInterval، ولكن... setTimeout.call(myArray, myArray.myMethod, 2000); // يطبع "صفر، واحد، اثنان" بعد ثانيتين setTimeout.call(myArray, myArray.myMethod, 2500, 2); // يطبع "اثنين" بعد 2.5 ثانية

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

    minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| المراجعة رقم 2 - 26 سبتمبر 2014.setInterval |*| https://site/User:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| تم إصدار هذا الإطار بموجب رخصة جنو العامة الصغرى، الإصدار 3 أو الأحدث. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ الدالة MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(this && thisمثيل MiniDaemon)) ( return; ) if (arguments.length< 2) { throw new TypeError("MiniDaemon - not enough arguments"); } if (oOwner) { this.owner = oOwner; } this.task = fTask; if (isFinite(nRate) && nRate >0) ( this.rate = Math.floor(nRate); ) if (nLen > 0) ( this.length = Math.floor(nLen); ) ) MiniDaemon.prototype.owner = null; MiniDaemon.prototype.task = null; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Infinity; /* يجب أن تكون هذه الخصائص للقراءة فقط */ MiniDaemon.prototype.SESSION = -1; MiniDaemon.prototype.INDEX = 0; MiniDaemon.prototype.PAUSED = true; MiniDaemon.prototype.BACKW = صحيح؛ /* الطرق العامة */ MiniDaemon.forceCall = function (oDmn) ( oDmn.INDEX += oDmn.BACKW ? -1: 1; if (oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn .BACKW) === false || oDmn.isAtEnd()) ( oDmn.pause(); return false; ) return true; ); /* طرق المثيلات */ MiniDaemon.prototype.isAtEnd = function () ( return this.BACKW ? isFinite(this.length) && this.INDEX< 1: this.INDEX + 1 >this.length; ); MiniDaemon.prototype.synchronize = function () ( if (this.PAUSED) ( return; ) ClearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = function () ( ClearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = الوظيفة (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; this.PAUSED = false; this.synchronize(); );

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

    بناء الجملة

    فار myDaemon = MiniDaemon الجديد( thisObject, أتصل مرة أخرى[ , معدل [, طول]]);

    وصف ملاحظات الاستخدام

    تُستخدم الدالة setInterval() بشكل شائع لتعيين تأخير للوظائف التي يتم تنفيذها مرارًا وتكرارًا، مثل الرسوم المتحركة. يمكنك إلغاء الفاصل الزمني باستخدام WindowOrWorkerGlobalScope.clearInterval() .

    إذا كنت ترغب في استدعاء وظيفتك مرة واحدةبعد التأخير المحدد، استخدم .

    قيود التأخير

    من الممكن أن تكون الفواصل متداخلة؛ أي أن رد الاتصال لـ setInterval() يمكنه بدوره استدعاء setInterval() لبدء تشغيل فاصل زمني آخر، على الرغم من أن الأول لا يزال مستمرًا. للتخفيف من التأثير المحتمل الذي يمكن أن يحدثه ذلك على الأداء، بمجرد تداخل الفواصل الزمنية بما يتجاوز خمسة مستويات، سيفرض المتصفح تلقائيًا قيمة أدنى قدرها 4 مللي ثانية للفاصل الزمني. سيتم تثبيت محاولات تحديد قيمة أقل من 4 مللي ثانية في الاستدعاءات المتداخلة بعمق إلى setInterval() إلى 4 مللي ثانية.

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

    تأكد من أن مدة التنفيذ أقصر من تكرار الفاصل الزمني

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

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

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

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

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

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

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

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

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

    الدالة welltest() ( if (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

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

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

    دالة besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400)) ) دالة draw() ( document.getElementById("test3").value += ++i if (i) >= 9) ClearInterval(window.timer1)) )

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

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

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

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

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

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

  • قمنا بتعيين إجمالي وقت "المغادرة"، على سبيل المثال، إلى 200 مللي ثانية.
  • إذا كان ارتفاع القائمة المنسدلة 20 بكسل، فمن الواضح أنه يمكننا تحريكها لأسفل بمقدار بكسل واحد لكل فاصل زمني قدره 10 مللي ثانية - وبعد ذلك خلال 200 مللي ثانية ستظهر القائمة بأكملها.
  • إذا كان ارتفاع القائمة المنسدلة 40 بكسل، فيجب علينا تحريكها للأسفل بمقدار بكسل واحد كل 5 مللي ثانية لكي تتناسب مع نفس القدر من الوقت.
  • وبهذا المنطق، إذا كان ارتفاع القائمة المنسدلة 200 بكسل، فيجب أن ننقلها إلى الأسفل بمقدار بكسل واحد كل 1 مللي ثانية. لكن هذه السرعة لا تعمل على جهاز الكمبيوتر الخاص بنا - فالمتصفح ببساطة ليس لديه الوقت لرسم الموضع الجديد للقائمة في ميلي ثانية واحدة. نعم. تمكنت Javascript من العد (ما الذي يجب حسابه؟) ، لكن المتصفح (Firefox) ليس لديه الوقت للعرض. الوضع النموذجي للويب.

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

  • قم بتعيين الوقت الإجمالي للتحقق من القائمة: الوقت = 224 (مللي ثانية).
  • قمنا بتعيين الحد الأدنى من الوقت لفترة زمنية واحدة في الدورة: التأخير = 3 (مللي ثانية).
  • قم بتعيين الحد الأدنى للخطوة لنقل القائمة: الإزاحة = 1 (px).
  • نقوم بتغيير كل هذا اعتمادًا على ارتفاع القائمة: 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(function())(slide_do(ts, maxtop, offset)), تأخير)

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