سؤال

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

الخيار أ:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

الخيار ب:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

هل هناك فرق بين استخدام setTimeout و setInterval?

هل كانت مفيدة؟

المحلول

أنها أساسا تحاول أن تفعل الشيء نفسه, ولكن setInterval النهج سوف يكون أكثر دقة من setTimeout النهج منذ setTimeout ينتظر 1000ms يدير وظيفة ثم يحدد مهلة أخرى.حتى فترة الانتظار هو في الواقع أكثر قليلا من 1000ms (أو أكثر إن وظيفة الخاص بك يأخذ وقت طويل تنفيذ).

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

في هذا كمان, يمكنك أن ترى بوضوح أن المهلة سوف تقع وراء ، في حين أن الفاصل هو تقريبا كل الوقت تقريبا 1 الدعوة/الثانية (التي السيناريو يحاول القيام به).إذا قمت بتغيير سرعة متغير في الجزء العلوي إلى شيء صغير مثل 20 (وهذا يعني أنها سوف محاولة تشغيل 50 مرة في الثانية) ، والفترة لم تصل إلى حد متوسط من 50 التكرار في الثانية.

التأخير هو دائما تقريبا لا تذكر, ولكن إذا كنت البرمجة شيئا دقيقة, يجب عليك أن تذهب ضبط النفس الموقت (الذي هو في جوهره مهلة مقرها الموقت باستمرار يضبط نفسه عن التأخير انها خلقت)

نصائح أخرى

هل هناك أي فرق؟

نعم. تنفذ مهلة وقت معين بعد استدعاء Settimeout ()؛ ينفذ الفاصل الزمني لفترة زمنية معينة بعد إطلاق الفاصل الزمني السابق.

ستلاحظ الفرق إذا استغرقت وظيفة dostuff () بعض الوقت لتنفيذها. على سبيل المثال، إذا كنا نمثل دعوة إلى settimeout / setinterval مع ., ، إطلاق النار من المهلة / الفاصل * وتنفيذ رمز جافا سكريبت مع [-----], ، الجدول الزمنية تبدو:

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

تعرض المضاعفات التالية هو إذا حرائق الفاصل الزمني في حين أن جافا سكريبت مشغول بالفعل بعمل شيء (مثل التعامل مع فاصل زمني سابق). في هذه الحالة، يتم تذكر الفاصل الزمني، ويحدث بمجرد انتهاء المعالج السابق وتحديد التحكم في المتصفح. لذلك على سبيل المثال لعملية dostuff () قصيرة في بعض الأحيان ([-]) وأحيانا طويلة ([-----]):

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]

• يمثل إطلاق فاصل إضافي لا يمكنه تنفيذ قانونه على الفور، وتمت في انتظار بدلا من ذلك.

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

.    *    •    •    x    •    •    x
     [------][------][------][------]

يمثل X إطلاق فاصل إضافي لا يمكن تنفيذه أو يتم إبداءه، لذلك تم تجاهله بدلا من ذلك.

إذا كانت دالة Dostuff () الخاصة بك عادة ما تستغرق وقتا أطول للتنفيذ من الفاصل الزمني الذي تم تعيينه لذلك، فإن المتصفح سيأكل وحدة المعالجة المركزية بنسبة 100٪ في محاولة لخدمة ذلك، وقد تصبح أقل استجابة.

ما الذي تستخدمه ولماذا؟

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

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

من حيث توافق المتصفح، يقوم Settimeout بترتيب SetInterval، ولكن جميع المتصفحات التي ستقابلها اليوم الدعم كلاهما. كان Straggler الأخير لسنوات عديدة IE Mobile في WinMO <6.5، ولكن نأمل أن يكون ذلك أيضا وراءنا الآن.

setinterval ()

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

إذا كنت ترغب في حلقة رمز الرسوم المتحركة أو في علامة الساعة، فاستخدم setInterval().

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);

Settimeout ()

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

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);

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

يجعل Setinterval من الأسهل إلغاء التنفيذ المستقبلي لرمزك. إذا كنت تستخدم Pettimeout، فيجب عليك تتبع معرف Timer في حال كنت ترغب في إلغائه لاحقا.

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

عكس

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);

أجد. setTimeout الطريقة أسهل في استخدامها إذا كنت ترغب في إلغاء المهلة:

function myTimeoutFunction() {
   doStuff();
   if (stillrunning) {
      setTimeout(myTimeoutFunction, 1000);
   }
}

myTimeoutFunction();

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

الفرق في أغراضهم.

setInterval()
   -> executes a function, over and over again, at specified time intervals  

setTimeout()
   -> executes a function, once, after waiting a specified number of milliseconds

إنها بهذه السهولة

تفاصيل أكثر تفاصيل هنا http://javascript.info/tutorial/settimeout-setinterval.

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

- على سبيل المثال، افعل اشياء() يستغرق 1500 ثانية. لكي تنفذ وأنت تفعل: setinterval (dostuff، 1000)؛
1) تشغيل المتصفح افعل اشياء() الذي يستغرق 1.5 ثانية. ليتم تنفيذها؛
2) بعد ~ 1 ثانية يحاول تشغيل افعل اشياء() تكرارا. لكن سابقا افعل اشياء() لا يزال ينفذ -> حتى يضيف المتصفح هذا التشغيل إلى قائمة الانتظار (للتشغيل بعد الانتهاء أولا).
3،4، ..) نفس إضافة إلى قائمة الانتظار للتنفيذ للتكرار المقبل، ولكن افعل اشياء() من السابق لا يزال قيد التقدم ...
كما النتيجة - المتصفح عالق.

لمنع هذا السلوك، فإن أفضل طريقة هي الركض settimeout داخل settimeout لمحاكاة setinterval.
لتصحيح المهلة بين مكالمات Settimeout، يمكنك استخدامها بديل تصحيح ذاتي إلى Setinterval JavaScript تقنية.

أنا استخدم pettimeout.

على ما يبدو الفرق هو settimeout يستدعي الطريقة مرة واحدة، يدعو setinterval إلى تكرارا.

فيما يلي مقالة جيدة توضح الفرق: البرنامج التعليمي: توقيت جافا سكريبت مع Settimeout و SetInterval

لقد قدمت اختبار بسيط ل setInterval(func, milisec), ، لأنني كنت فضوليا ما يحدث عندما يكون استهلاك وقت العمل أكبر من مدة الفاصل الزمني.

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

لقد اختبرت هذا على Chrome V23. آمل أن يتم التنفيذ المحدد في جميع المتصفحات الحديثة.

window.setInterval(function(start) {
    console.log('fired: ' + (new Date().getTime() - start));
    wait();
  }, 1000, new Date().getTime());

خرج وحدة التحكم:

fired: 1000    + ~2500 ajax call -.
fired: 3522    <------------------'
fired: 6032
fired: 8540
fired: 11048

ال wait الوظيفة هي مجرد مساعد حظر الموضوع - مكالمة أجاكس متزامنة والتي تستغرق بالضبط 2500 مللي ثانية المعالجة في جانب الخادم:

function wait() {
    $.ajax({
        url: "...",
        async: false
    });
}

سيكون لك التعليمات البرمجية الخاصة بك إغاثة تنفيذ مختلفة، وفي بعض المشاريع، مثل الألعاب عبر الإنترنت أنها غير مقبولة. أولا، ماذا يجب أن تفعل ذلك، لجعل التعليمات البرمجية الخاصة بك مع نفس المخططات الإذاعية، يجب عليك تغيير "MyTimeOutFunction" إلى هذا:

function myTimeoutFunction()
{
    setTimeout(myTimeoutFunction, 1000);
    doStuff();
}
myTimeoutFunction()

بعد هذا التغيير، سيكون مساويا

function myTimeoutFunction()
{
    doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

ولكن، ستظل ليس لها نتيجة مستقرة، لأن JS هو خيوط مفردة. في الوقت الحالي، إذا كان مؤشر ترابط JS مشغولا بشيء ما، فلن يتمكن من تنفيذ وظيفة رد الاتصال الخاصة بك، وسيتم تأجيل التنفيذ لمدة 2-3 MSEC. هل لديك 60 عملية إعدام في الثانية في الثانية، وفي كل مرة يكون لديك تأخير عشوائي 1-3 ثواني، سيكون غير مقبول تماما (بعد دقيقة واحدة، سيكون حوالي 7200 MSEC تأخير)، ويمكنني تقديم المشورة لاستخدام شيء مثل هذا:

    function Timer(clb, timeout) {
        this.clb = clb;
        this.timeout = timeout;
        this.stopTimeout = null;
        this.precision = -1;
    }

    Timer.prototype.start = function() {
        var me = this;
        var now = new Date();
        if(me.precision === -1) {
            me.precision = now.getTime();
        }
        me.stopTimeout = setTimeout(function(){
            me.start()
        }, me.precision - now.getTime() + me.timeout);
        me.precision += me.timeout;
        me.clb();
    };

    Timer.prototype.stop = function() {
        clearTimeout(this.stopTimeout);
        this.precision = -1;
    };

    function myTimeoutFunction()
    {
        doStuff();
    }

    var timer = new Timer(myTimeoutFunction, 1000);
    timer.start();

سيضمن هذا الرمز فترة التنفيذ المستقرة. حتى الخيط سيكون مشغولا، وسيتم تنفيذ التعليمات البرمجية الخاصة بك بعد 1005 mseconds، في المرة القادمة سيكون لها مهلة ل 995 msec، وسوف تكون النتيجة مستقرة.

أن ننظر إليها بشكل مختلف قليلا: SetInterval يؤمن أن رمز يتم تشغيله في كل فترة زمنية مشددة (أي 1000ms، أو مقدار تحديده) أثناء تعيين SettimeOut الوقت الذي ينتظره حتى يقوم بتشغيل التعليمات البرمجية. وبما أن الأمر يتطلب milliseconds إضافية لتشغيل التعليمات البرمجية، فإنه يضيف ما يصل إلى 1000 مللي ثانية وبالتالي، يتم تشغيل Settimeout مرة أخرى في أوقات غير دقيقة (أكثر من 1000ms).

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

يعيد كل من SetInterval و Settimeout معرف توقيت يمكنك استخدامه لإلغاء التنفيذ، أي قبل أن يتم تشغيل المهلة. لإلغاء الاتصال عليك إما CleartinVal أو ClearTimeout مثل هذا:

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

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

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

يمكنك التحقق من صحة الإجابة Bobince بنفسك عند تشغيل JavaScript أو التحقق من ذلك jsfiddle.

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});

الفرق واضح في وحدة التحكم:

enter image description here

فقط إضافة إلى ما قيل بالفعل ولكن إصدار Settimeout من التعليمات البرمجية سوف يصل أيضا إلى Maximum call stack size والتي سوف يمنعها من العمل. نظرا لعدم وجود حالة أساسية للوظيفة العودية للتوقف عندها حتى لا تتمكن من تشغيلها مدى الحياة.

أظن SetInterval و SetTimeout مختلفة. SetInterval ينفذ الكتلة وفقا لمجموعة الوقت أثناء، SetTimeout ينفذ كتلة التعليمات البرمجية مرة واحدة.

جرب هذه المجموعة من الرموز بعد ثوان العد التنازلي المهلة:

setInterval(function(e){
    alert('Ugbana Kelvin');
}, 2000);

ثم حاول

setTimeout(function(e){
    alert('Ugbana Kelvin');
}, 2000);

يمكنك أن ترى الاختلافات لنفسك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top