سؤال

أنا أكتب webapp (متوافق مع Firefox فقط) الذي يستخدم الاقتراع الطويل (عبر قدرات AJQUERY AJAX) لإرسال تحديثات ثابتة أو أقل من الخادم إلى العميل. أنا قلق بشأن آثار ترك هذا الركض لفترات طويلة من الزمن ، على سبيل المثال ، طوال اليوم أو بين عشية وضحاها. الهيكل العظمي الكود الأساسي هو:

function processResults(xml)
{
    // do stuff with the xml from the server
}

function fetch()
{
    setTimeout(function ()
    {
        $.ajax({
            type: 'GET',
            url: 'foo/bar/baz',
            dataType: 'xml',
            success: function (xml)
            {
                processResults(xml);
                fetch();
            },
            error: function (xhr, type, exception)
            {
                if (xhr.status === 0)
                {
                console.log('XMLHttpRequest cancelled');
                }
                else
                {
                    console.debug(xhr);
                    fetch();
                }
            }
        });
    }, 500);
}

(نصف ثانية "النوم" هو حتى لا يطرق العميل الخادم إذا كانت التحديثات تعود إلى العميل بسرعة - وهو عادة ما تكون كذلك.)

بعد مغادرة هذا الركض بين عشية وضحاها ، فإنه يميل إلى جعل زحف Firefox. كنت أفكر في أن هذا يمكن أن يكون سببًا جزئيًا بسبب عمق كومة كبير لأنني كتبت بشكل أساسي وظيفة عودية بلا حدود. ومع ذلك ، إذا استخدمت Firebug ورميت نقطة توقف fetch, ، يبدو أن هذا ليس هو الحال. المكدس الذي يظهر لي Firebug هو حوالي 4 أو 5 إطارات عميقة ، حتى بعد ساعة.

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

هل الحل الأفضل لمجرد القيام بتحديث صعب على الصفحة بشكل دوري ، على سبيل المثال ، مرة واحدة كل ساعة؟ هل هناك نمط تصميم أفضل/أصغر طويل لا يصب بأذى على المتصفح حتى بعد الركض لمدة 8 أو 12 ساعة؟ أو هل يجب أن أتخطى الاقتراع الطويل تمامًا واستخدام نمط "تحديث ثابت" مختلف لأنني عادة ما أعرف مدى تواتر الخادم استجابة لي؟

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

المحلول

من الممكن أيضًا أن يكون Firebug. أنت وحدة التحكم.

حاول تعطيلها ، معرفة ما إذا كان ذلك يساعد.

نصائح أخرى

أظن أن الذاكرة تتسرب من processResults().

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

لا ينبغي أن يكون مجموعتك عميقة ، لأن fetch() يعود على الفور. ليس لديك حلقة متكررة بلا حدود.

قد ترغب في استخدام Firefox تسرب مراقبة الوظيفة الإضافية لمساعدتك في العثور على تسرب الذاكرة.

عمق المكدس 4-5 صحيح. setTimeout و $.ajax هي المكالمات غير المتزامنة ، والتي تعود على الفور. يتم استدعاء رد الاتصال لاحقًا من قبل المتصفح مع مكدس استدعاء فارغ. نظرًا لأنك لا تستطيع تنفيذ الاقتراع الطويل بطريقة متزامنة ، يجب عليك استخدام هذا النهج العودية. لا توجد طريقة لجعلها تكرارية.

أظن أن سبب هذا التباطؤ هو أن الكود الخاص بك يحتوي على تسرب ذاكرة. يمكن أن يكون التسرب إما في $.ajax بواسطة jQuery (من غير المحتمل جدًا) أو في processResults يتصل.

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

تدعم الإصدارات الحديثة من jQuery التقدم لفترة طويلة بشكل افتراضي. وبهذه الطريقة ، يمكنك التأكد من أن Yhou ليس Deppening على ذكاء المتصفح للتعامل مع مكالمتك العودية اللانهائية. عند استدعاء $.ajax() الطريقة يمكنك استخدام الكود أدناه لإجراء استطلاع طويل جنبًا إلى جنب مع انتظار آمن قدره 500 ميلي ثانية قبل مكالمة جديدة.

function myLongPoll(){
    setTimeout(function(){
        $.ajax({
            type:'POST',
            dataType: 'JSON',
            url: 'http://my.domain.com/action',
            data: {},
            cache: false,
            success:function(data){

                //do something with the result

            },
            complete: myLongPoll, 
            async : false,
            timeout: 5000
        });
   //Doesn't matter how long it took the ajax call, 1 milisec or 
   //5 seconds (timeout), the next call will only happen after 2 seconds
   }, 2000);

بهذه الطريقة يمكنك التأكد من أن $.ajax() تم إغلاق المكالمة قبل بدء التشغيل التالي. يمكن إثبات ذلك بإضافة بسيطة console.log() في السابق والآخر بعد $.ajax() يتصل.

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