2009-03-23 16 views
50

मेरे पास जावास्क्रिप्ट है जो पूरी गणना करता है और साथ ही डीओएम से मूल्यों को पढ़/लिखता है। पृष्ठ बहुत बड़ा है, इसलिए यह 100% CPU उपयोग के साथ ब्राउज़र को एक मिनट तक (कभी-कभी लंबे समय तक IE) तक लॉक कर देता है।ब्राउजर को लॉक करने से लंबे समय तक चलने वाले जावास्क्रिप्ट को रोकें

क्या ऐसा होने से रोकने के लिए जावास्क्रिप्ट को अनुकूलित करने पर कोई संसाधन है (मुझे लगता है कि फ़ायरफ़ॉक्स की लंबी चल रही स्क्रिप्ट चेतावनी को बंद करना है)?

उत्तर

44

यदि आप अपनी गणना एल्गोरिदम को किसी चीज में बदल सकते हैं जिसे इसे सामान्य रूप से कहा जा सकता है, तो आप कम समय के साथ setTimeout का उपयोग करके ब्राउज़र को लगातार अंतराल पर नियंत्रण जारी कर सकते हैं।

उदाहरण के लिए

, कुछ इस तरह ...

function doCalculation() 
{ 
    //do your thing for a short time 

    //figure out how complete you are 
    var percent_complete=.... 

    return percent_complete; 
} 

function pump() 
{ 
    var percent_complete=doCalculation(); 

    //maybe update a progress meter here! 

    //carry on pumping? 
    if (percent_complete<100) 
    { 
     setTimeout(pump, 50); 
    } 
} 

//start the calculation 
pump(); 
+2

क्या आप जानते हैं कि यह अभी भी काम करेगा यदि आप 'सेटटाइमआउट (पंप, 0)' का उपयोग करते हैं? या क्या यह संभवतः ब्राउज़र इनपुट को पूर्व-खाली कर देगा जो माउस इनपुट का जवाब देता है, प्रगति मीटर या अन्य डीओएम तत्व अपडेट करता है? – Andy

+0

@ एंडी हां 'सेटटाइमआउट' 0 के साथ भी मदद करेगा। [इस प्रश्न] के कुछ जवाब देखें (https://stackoverflow.com/questions/779379/why-is-settimeoutfn-0- कभी-कभी- उपयोगी)। – ShreevatsaR

1

आप थ्रेड में लंबी चल रही गणना करने का प्रयास कर सकते हैं (JavaScript and Threads देखें), हालांकि वे बहुत पोर्टेबल नहीं हैं।

आप प्रदर्शन बाधाओं को खोजने के लिए कुछ जावास्क्रिप्ट प्रोफाइलर का उपयोग करने का भी प्रयास कर सकते हैं। Firebug प्रोफाइलिंग जावास्क्रिप्ट का समर्थन करता है।

7

टाइमआउट का उपयोग करें।

अपने लूप की सामग्री को अलग-अलग कार्यों में डालकर, और सेटटाइमआउट() से उन्हें 50 या उससे अधिक समय के साथ कॉल करके, जावास्क्रिप्ट धागे का नियंत्रण प्राप्त करेगा और कुछ समय बाद वापस आ जाएगा एक देखने के लिए यूआई।

एक अच्छी कार्यप्रणाली here है।

2

मैं in-browser performance के बारे में कुछ समय पहले भी ब्लॉग की थी, लेकिन मुझे यहाँ आप के लिए डोम से संबंधित लोगों को संक्षेप में दोहराएँ।

  • जितना संभव हो सके डीओएम अपडेट करें। अपने परिवर्तन इन-मेमोरी डीओएम ऑब्जेक्ट्स में करें और उन्हें केवल एक बार डोम में संलग्न करें।
  • आंतरिक HTML का उपयोग करें। यह अधिकांश ब्राउज़रों में डीओएम विधियों से तेज़ है।
  • नियमित ईवेंट हैंडलिंग के बजाय ईवेंट प्रतिनिधिमंडल का उपयोग करें।
  • जानें कि कौन सी कॉल महंगे हैं, और उनसे बचें। उदाहरण के लिए, jQuery में, $ ("div.className") $ ("# someId") से अधिक महंगा होगा।

तो फिर वहाँ स्वयं JavaScript को कुछ संबंधित हैं: संभव के रूप में

  • लूप रूप में छोटे। यदि आपके पास एक ऐसा फ़ंक्शन है जो डोम नोड्स एकत्र करता है, और दूसरा जो उन्हें संसाधित करता है, तो आप दो बार लूप कर रहे हैं। इसके बजाय, नोड्स एकत्र करने वाले फ़ंक्शन में एक अनाम फ़ंक्शन पास करें, और नोड्स को संसाधित करें क्योंकि आप उन्हें एकत्र कर रहे हैं।
  • जब संभव हो तो मूल कार्यक्षमता का उपयोग करें। उदाहरण के लिए, प्रत्येक इटरेटर के लिए।
  • थोड़ी देर में ब्राउज़र को सांस लेने के लिए सेटटाइमआउट का उपयोग करें।
  • महंगे कार्यों के लिए जिनके पास idempotent आउटपुट है, परिणाम कैश करें ताकि आपको इसे पुन: सम्मिलित न करना पड़े।

मेरे ब्लॉग (ऊपर लिंक) पर कुछ और है।

1

यह अभी भी थोड़ा खून बह रहा है, लेकिन फ़ायरफ़ॉक्स 3.5 में इन चीजों को वेब वर्कर्स कहा जाता है, हालांकि मुझे अन्य ब्राउज़रों में उनके समर्थन के बारे में निश्चित नहीं है। जब कार्यकर्ता धागे कर रहे हैं http://ejohn.org/blog/web-workers/

और Simulated Annealing शायद, इसके बारे में सबसे सरल उदाहरण है अगर आप कताई फ़ायरफ़ॉक्स लोगो पर ध्यान देंगे अप जमता नहीं,:

श्री Resig यहां उन पर एक लेख है उनके अनुरोध (इस प्रकार ब्राउज़र को जमा नहीं कर रहे हैं)।

+0

वेब श्रमिकों का जवाब यहां क्यों नहीं है? –

+0

खैर मैंने इसका उत्तर 9 0 में दिया था, तो शायद यह व्यापक रूप से उपयोग नहीं किया गया था ... – leeand00

+0

अच्छा बिंदु, ठीक है, यह निश्चित रूप से अब शीर्ष पर होना चाहिए। सेटटाइमआउट का उपयोग करना मुझे हैकी लगता है, इससे कोई फर्क नहीं पड़ता कि आप क्या कर रहे हैं जब तक कि आपको वास्तव में किसी चीज़ के लिए टाइमआउट की आवश्यकता न हो। यदि आप अभी क्रोम विंडोज पर codepen.io पर जाते हैं और जटिलता ओ (एन!) कहने के साथ एक एल्गोरिदम करते हैं जैसे स्ट्रिंग "एबीसीडीएफजीएचजेजेकेएलएमएनओपी" के सभी क्रमपरिवर्तनों को ढूंढना, आपका ब्राउज़र लॉक हो जाएगा और उत्तरदायी नहीं होगा। एक कार्यकर्ता थ्रेड में यूआई अपने आप चल रहा है। यह स्पष्ट रूप से सही जवाब है। –

1

मेरा अनुभव यह है कि विशेष रूप से आईई में डीओएम हेरफेर, "कोर" जावास्क्रिप्ट (लूपिंग इत्यादि) से प्रदर्शन के लिए एक मुद्दा है।

यदि आप नोड्स बना रहे हैं, तो आईई में ऐसा करने के लिए आईई में बहुत तेज है और एचटीएमएल स्ट्रिंग बनाकर और कंटेनर पर आंतरिक HTML को बनाना, जैसे createElement/appendChild।

0

आप

$(xmlDoc).find("Object").each(function(arg1) { 
    (function(arg1_received) { 
       setTimeout(function(arg1_received_reached) { 

        //your stuff with the arg1_received_reached goes here 

       }(arg1_received), 0) 
      })(arg1) 
}(this)); 

द्वारा या के लिए कोड को छोटा छोरों "के लिए"

for (var i = 0 ; i < 10000 ; i = i + 1) { 
    (function(arg1_received) { 
     setTimeout(function(arg1_received_reached) { 

      //your stuff with the arg1_received_reached goes here 

     }(arg1_received), 0) 
    })(arg1_to_send) 
} 

मैं एक ही समस्या थी और मेरे ग्राहकों के रूप में "मार पेज" त्रुटि इस रिपोर्टिंग कर रहा था की कोशिश की कोशिश कर सकते। लेकिन अब मैं juz उस के लिए एक अच्छा समाधान मिला है। :)

संबंधित मुद्दे