لماذا تتسبب مكالمات SetTimeOut () المتعددة في تأخر الكثير؟

StackOverflow https://stackoverflow.com/questions/4211046

سؤال

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

تم اختباره في Internet Explorer 9 ، يعمل الرسوم المتحركة بسرعة حقيقية (يجب أن يستغرق الأمر 1.6 ثانية واستغرق الأمر 1.6 ثانية بالضبط). أي متصفح آخر سوف يتخلف بشكل فظيع ، مع أوقات الرسوم المتحركة من 4 ثوان (Firefox 3 و 4 ، Chrome ، Opera) وشئ مثل 20 ثانية في IE 8 وما يلي.

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

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

تحرير: لتوضيح الاستجابة للتعليقات ، إليك الخطوط العريضة للرمز:

link.onclick = function() {
    clearTimeout(colourFadeTimeout);
    colourFadeTimeout = setTimeout("colourFade(0);",25);

    clearTimeout(arrowScrollTimeout);
    arrowScrollTimeout = setTimeout("arrowScroll(0);",25);

    clearTimeout(pageFadeOutTimeout);
    pageFadeOutTimeout = setTimeout("pageFadeOut(0);",25);

    clearTimeout(pageFadeInTimeout);
    pageFadeInTimeout = setTimeout("pageFadeIn(0);",25);
}

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

يمكنك رؤية الصفحة في http://adamhaskell.net/cw/index.html (اسم المستخدم: knockknock ؛ كلمة المرور: goaway) (يحتوي على صوت وموسيقى ، والتي يمكن تعطيلها ، ولكن يتم تحذيرها!) - JavaScript فوضوي للغاية لأنني لم أقم بتنظيمها بشكل صحيح حقًا ، لكن تم التعليق عليها قليلاً يمكنك أن ترى ما هي الفكرة العامة.

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

المحلول

عدة أشياء:

  1. مهلةك هي 25 مللي ثانية. هذا يترجم إلى 40 إطارًا في الثانية وهو إطار مرتفع للغاية لمحاولة تحقيقه عبر JavaScript. خاصة بالنسبة للأشياء التي تنطوي على معالجة DOM التي قد تؤدي إلى انتعاش. قم بزيادةها إلى 50 أو 60. يجب أن تكون 15 إطارًا في الثانية أكثر من سائل بما يكفي لأنواع الرسوم المتحركة التي تقوم بها. أنت لا تحاول عرض مقاطع الفيديو هنا ، ما عليك سوى نقل الأشياء حول الصفحة.

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

    setTimeout(function(){
        pageFadeIn(0)
    },50);
    

    لن يتم تجميع هذا إلا مرة واحدة عند تحميل البرنامج النصي.

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


إجابة إضافية:

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

من بين الأشياء التي قمت بها لتحسين اللعبة هي:

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

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

نصائح أخرى

حسنًا ، هذا كثير من JavaScript (على الرغم من "جرعة الرباعي من الذهول" :)

أنت تطلق الكثير من تسلسل setTimeout ، لست متأكدًا من مدى تحسين محركات JS لهذا الغرض .. خاصةً <= 8

حسنًا ، ربما مجرد اقتراح تقريبي ... ربما يمكنك كتابة محرك توقيت صغير.

حافظ على كائن عالمي يخزن أحداثك الحالية الموقوتة مع الوظيفة لتشغيلها ، والتأخير ...

ثم يكون لديك معالج setTimeOut واحد يتحقق من هذا الكائن العالمي ، ويقلل من التأخير في كل تكرار واتصل بالوظيفة عندما يصبح التأخير <0

إن الحدث العالمي يبدو مثل هذا:

var events = {

        fade1 : {
            fn : func_name,
            delay : 25,
            params : {}
        }

        fadeArrow : {
            fn : func_name,
            delay : 500,
            params : {}
        }

        slideArrow : {
            fn : func_name,
            delay : 500,
            params : {
                arrow:some_value
            }
        }

    }

ثم قم بإنشاء وظيفة للحلق من خلال هذه في فاصل زمني (ربما 10 أو 20 مللي ثانية) وقلل من تأخيراتك حتى يكملوا الوظيفة وإطلاقها مع params باعتبارها paramer للدالة (تحقق من الدالة.

مرة واحدة ، النار settimeout مرة أخرى مع نفس التأخير ..

لإلغاء حدث فقط قم بإلغاء ضبط العقار من قائمة الأحداث ..

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

من شأنه أن يقلل كل شيء إلى معالج مهلة واحدة ..

(مجرد فكرة)

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