सेटटाइमआउट (fn, 0) कभी-कभी उपयोगी क्यों होता है?


872

मैंने हाल ही में एक बल्कि गंदा बग में भाग लिया है, जिसमें कोड <select>जावास्क्रिप्ट के माध्यम से गतिशील रूप से लोड हो रहा था । इस गतिशील रूप से भरी हुई <select>एक पूर्व चयनित मूल्य था। IE6 में, हम पहले से ही चयनित ठीक करने के लिए कोड था <option>, क्योंकि कभी कभी <select>के selectedIndexमूल्य चयनित से तालमेल न बिठा होगा <option>s ' indexनीचे के रूप में विशेषता,:

field.selectedIndex = element.index;

हालाँकि, यह कोड काम नहीं कर रहा था। भले ही फ़ील्ड selectedIndexसही ढंग से सेट की जा रही हो, गलत इंडेक्स का चयन किया जाएगा। हालांकि, अगर मैंने alert()सही समय पर एक स्टेटमेंट अटका दिया है, तो सही विकल्प का चयन किया जाएगा। यह सोचते हुए कि यह कुछ समय का मुद्दा हो सकता है, मैंने कुछ यादृच्छिक कोशिश की, जिसे मैंने पहले कोड में देखा था:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

और यह काम किया!

मुझे अपनी समस्या का हल मिल गया है, लेकिन मैं असहज हूं कि मुझे नहीं पता कि यह मेरी समस्या को ठीक क्यों करता है। क्या किसी के पास आधिकारिक स्पष्टीकरण है? अपने फ़ंक्शन को "बाद में" उपयोग करके मैं किस ब्राउज़र समस्या से बच रहा हूं setTimeout()?


2
अधिकांश प्रश्न यह वर्णन करते हैं कि यह उपयोगी क्यों है। यदि आपको यह जानने की आवश्यकता है कि ऐसा क्यों होता है - मेरा उत्तर पढ़ें: stackoverflow.com/a/23747597/1090562
साल्वाडोर डाली

18
फिलिप रॉबर्ट्स ने अपनी बात "यहाँ क्या बिल्ली घटना पाश है?" youtube.com/watch?v=8aGhZQkoFbQ
वासा

यदि आप जल्दबाज़ी में हैं, तो यह वीडियो का वह हिस्सा है जो प्रश्न को ठीक से संबोधित करना शुरू करता है: youtu.be/8aGhZQkoFbQ?t=14m54s । भले ही, पूरा वीडियो निश्चित रूप से देखने लायक है।
विलियम हैम्पशायर

4
setTimeout(fn)setTimeout(fn, 0)btw के समान है ।
विस्कॉन्सिन

जवाबों:


827

प्रश्न में, एक दौड़ की स्थिति मौजूद थी :

  1. ब्राउज़र की कोशिश ड्रॉप-डाउन सूची को आरम्भ करने के लिए, अपने चयनित सूचकांक को अपडेट करने के लिए तैयार है, और
  2. चयनित कोड सेट करने के लिए आपका कोड

आपका कोड लगातार इस दौड़ को जीत रहा था और ब्राउज़र के तैयार होने से पहले ड्रॉप-डाउन चयन को सेट करने का प्रयास कर रहा था, जिसका अर्थ है कि बग दिखाई देगा।

यह दौड़ मौजूद थी क्योंकि जावास्क्रिप्ट में निष्पादन का एक धागा है जो पेज रेंडरिंग के साथ साझा किया गया है। वास्तव में, JavaScript चलाना DOM के अपडेट को ब्लॉक कर देता है।

आपका समाधान था:

setTimeout(callback, 0)

setTimeoutकॉलबैक के साथ आमंत्रित करना , और दूसरा तर्क के रूप में शून्य कॉलबैक को एसिंक्रोनस रूप से चलाने के लिए शेड्यूल करेगा कम से कम देरी के बाद - जो कि टैब के फोकस होने पर 10ms के आसपास होगा और निष्पादन का जावास्क्रिप्ट थ्रेड व्यस्त नहीं है।

ओपी का समाधान, इसलिए लगभग 10ms तक देरी करना था, चयनित सूचकांक की स्थापना। इससे ब्राउज़र को बग को ठीक करने के लिए DOM को इनिशियलाइज़ करने का मौका मिला।

इंटरनेट एक्सप्लोरर के हर संस्करण में विचित्र व्यवहारों का प्रदर्शन किया गया था और इस तरह का वर्कअराउंड कई बार आवश्यक था। वैकल्पिक रूप से यह ओपी के कोडबेस में एक वास्तविक बग हो सकता है।


फिलिप रॉबर्ट्स बात करते हैं "क्या घटना लूप है?" अधिक गहन स्पष्टीकरण के लिए।


276
'समाधान यह है कि जावास्क्रिप्ट निष्पादन को "थपथपाना" है ताकि रेंडर थ्रेड को पकड़ लिया जा सके।' पूरी तरह से सच नहीं है, जो सेटटाइमआउट करता है वह ब्राउज़र इवेंट कतार में एक नया ईवेंट जोड़ देता है और रेंडरिंग इंजन पहले से ही उस कतार में है (पूरी तरह से सच नहीं है, लेकिन पर्याप्त रूप से बंद है) इसलिए यह सेटटाइमआउट इवेंट से पहले निष्पादित हो जाता है।
डेविड मुल्डर

48
हां, यह अधिक विस्तृत और अधिक सही उत्तर है। लेकिन लोगों को यह समझने के लिए मेरा "पर्याप्त रूप से सही" है कि चाल क्यों काम करती है।
स्टेटिक्सन

2
@DavidMulder, क्या इसका अर्थ है ब्राउज़र पार्स सीएसएस और जावास्क्रिप्ट निष्पादन थ्रेड से अलग थ्रेड में रेंडरिंग?
जेसन

8
नहीं, उन्हें एक ही धागे में सिद्धांत रूप में रखा गया है अन्यथा डोम हेरफेर की कुछ पंक्तियां हर समय रिफ्लोज़ को ट्रिगर करती हैं जो निष्पादन की गति पर बेहद बुरा प्रभाव डालती हैं।
डेविड मूलर

30
यह वीडियो सबसे अच्छा स्पष्टीकरण है कि हमें क्यों सेट किया गया है 0 2014.jsconf.eu/speakers/…
davibq

665

प्रस्तावना:

कुछ अन्य उत्तर सही हैं, लेकिन वास्तव में यह नहीं समझाते कि समस्या का हल क्या है, इसलिए मैंने यह उत्तर उस विस्तृत चित्रण को प्रस्तुत करने के लिए बनाया।

जैसे, मैं एक विस्तृत चलनाsetTimeout() पोस्ट कर रहा हूं कि ब्राउज़र क्या करता है और कैसे मदद करता है । यह लंबा दिखता है लेकिन वास्तव में बहुत सरल और सीधा है - मैंने इसे बहुत विस्तृत बना दिया।

अद्यतन: मैंने नीचे दिए गए विवरण को लाइव-प्रदर्शित करने के लिए एक JSField बनाया है: http://jsfiddle.net/C2YBE-31/ । इसे किकस्टार्ट करने में मदद करने के लिए @ThangChung को बहुत धन्यवाद

UPDATE2: बस के मामले में JSFiddle वेब साइट मर जाती है, या कोड को हटा देती है, मैंने बहुत ही अंत में इस उत्तर में कोड जोड़ा।


विवरण :

एक "कुछ कुछ" बटन और परिणाम div के साथ एक वेब ऐप की कल्पना करें।

onClick"कुछ करना" बटन के लिए हैंडलर एक समारोह कॉल "LongCalc ()", जो 2 काम करता है:

  1. बहुत लंबी गणना करता है (कहते हैं कि 3 मिनट लगते हैं)

  2. परिणाम div में गणना के परिणाम प्रिंट करता है।

अब, आपके उपयोगकर्ता इसका परीक्षण करना शुरू करते हैं, "कुछ करें" बटन पर क्लिक करें, और पृष्ठ 3 मिनट के लिए कुछ भी नहीं करने के लिए बैठता है, वे बेचैन हो जाते हैं, फिर से बटन पर क्लिक करें, 1 मिनट तक प्रतीक्षा करें, कुछ भी नहीं होता है, फिर से बटन पर क्लिक करें ...

समस्या स्पष्ट है - आप एक "स्थिति" DIV चाहते हैं, जो दिखाता है कि क्या चल रहा है। आइए देखें कि यह कैसे काम करता है।


तो आप एक "स्थिति" DIV (शुरू में खाली) जोड़ते हैं, और 4 चीजों को करने के लिए onclickहैंडलर (फ़ंक्शन LongCalc()) को संशोधित करते हैं:

  1. स्थिति की गणना करें "गणना ... स्थिति DIV में ~ 3 मिनट लग सकते हैं"

  2. बहुत लंबी गणना करता है (कहते हैं कि 3 मिनट लगते हैं)

  3. परिणाम div में गणना के परिणाम प्रिंट करता है।

  4. स्थिति की गणना "किया गया" स्थिति DIV में करें

और, आप खुशी-खुशी उपयोगकर्ताओं को पुन: परीक्षण करने के लिए ऐप देते हैं।

वे बहुत गुस्से में दिख रहे हैं। और समझाएं कि जब उन्होंने बटन पर क्लिक किया, तो स्टेटस DIV को "कैलकुलेटिंग ..." स्टेटस के साथ अपडेट नहीं किया गया !!!


आप अपना सिर खुजलाते हैं, StackOverflow (या डॉक्स या Google को पढ़ते हैं) के आसपास पूछते हैं, और समस्या का एहसास करते हैं:

ब्राउज़र अपने सभी "TODO" कार्यों (UI कार्य और जावास्क्रिप्ट आदेश दोनों) को एक कतार में घटनाओं से उत्पन्न करता है । और दुर्भाग्य से, नए "परिकलन ..." के साथ "स्थिति" DIV को फिर से आरेखण किया गया है। मान एक अलग TODO है जो कतार के अंत में जाता है!

यहां आपके उपयोगकर्ता के परीक्षण के दौरान घटनाओं का टूटना है, प्रत्येक घटना के बाद कतार की सामग्री:

  • कतार: [Empty]
  • घटना: बटन पर क्लिक करें। घटना के बाद कतार:[Execute OnClick handler(lines 1-4)]
  • घटना: OnClick हैंडलर में पहली पंक्ति निष्पादित करें (जैसे स्थिति DIV मान बदलें)। घटना के बाद कतार [Execute OnClick handler(lines 2-4), re-draw Status DIV with new "Calculating" value]:। कृपया ध्यान दें कि जबकि DOM परिवर्तन तुरंत होते हैं, उसी DOM तत्व को फिर से ड्रा करने के लिए, जिसे आपको एक नई घटना की आवश्यकता होती है, जो DOM परिवर्तन से शुरू होता है, जो कतार के अंत में चला गया
  • मुसीबत!!! मुसीबत!!! विवरण नीचे समझाया गया है।
  • घटना: हैंडलर (गणना) में दूसरी पंक्ति निष्पादित करें। के बाद कतार: [Execute OnClick handler(lines 3-4), re-draw Status DIV with "Calculating" value]
  • घटना: हैंडलर में तीसरी पंक्ति निष्पादित करें (परिणाम DIV को पॉप्युलेट करें)। के बाद कतार: [Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result]
  • घटना: हैंडलर में 4 वीं पंक्ति निष्पादित करें ("DONE" के साथ स्थिति DIV को पॉप्युलेट करें)। कतार: [Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value]
  • घटना: हैंडलर उप returnसे निहित निष्पादित onclick। हम कतार से "Execute OnClick हैंडलर" लेते हैं और कतार पर अगले आइटम को निष्पादित करना शुरू करते हैं।
  • नोट: चूंकि हमने पहले ही गणना समाप्त कर ली है, उपयोगकर्ता के लिए 3 मिनट पहले ही बीत चुके हैं। फिर से ड्रा इवेंट नहीं हुआ !!!
  • इवेंट: "गणना" मान के साथ स्थिति DIV को फिर से ड्रा करें। हम फिर से ड्रा करते हैं और उस कतार से बाहर निकालते हैं।
  • घटना: परिणाम मान के साथ परिणाम DIV को फिर से ड्रा करें। हम फिर से ड्रा करते हैं और उस कतार से बाहर निकालते हैं।
  • घटना: "Done" मान के साथ स्थिति DIV को फिर से ड्रा करें। हम फिर से ड्रा करते हैं और उस कतार से बाहर निकालते हैं। तेज-तर्रार दर्शकों को "स्थिति गणना" के साथ एक माइक्रोसेकंड के अंश के लिए चमकती मूल्य की भी गणना हो सकती है।

तो, अंतर्निहित समस्या यह है कि "स्थिति" DIV के लिए पुन: ड्रा इवेंट को अंत में कतार में रखा गया है, "निष्पादन पंक्ति 2" घटना के बाद, जिसमें 3 मिनट लगते हैं, इसलिए वास्तविक पुन: ड्रा तब तक नहीं होता है गणना के बाद किया जाता है।


बचाव के लिए आता है setTimeout()। यह कैसे मदद करता है? क्योंकि लंबे समय से निष्पादित कोड को कॉल करके setTimeout, आप वास्तव में 2 ईवेंट बनाते हैं: setTimeoutनिष्पादन ही, और (0 टाइमआउट के कारण), कोड निष्पादित होने के लिए अलग कतार प्रविष्टि।

इसलिए, अपनी समस्या को ठीक करने के लिए, आप अपने onClickहैंडलर को दो कथन (एक नए कार्य या बस एक ब्लॉक में onClick) होने के लिए संशोधित करते हैं :

  1. स्थिति की गणना करें "गणना ... स्थिति DIV में ~ 3 मिनट लग सकते हैं"

  2. setTimeout()0 टाइमआउट और LongCalc()कार्य करने के लिए कॉल के साथ निष्पादित करें

    LongCalc()फ़ंक्शन लगभग पिछली बार के समान ही है, लेकिन स्पष्ट रूप से "गणना ..." स्थिति नहीं है पहला चरण के रूप में DIV अपडेट; और इसके बजाय तुरंत गणना शुरू करता है।

तो, घटना क्रम और कतार अब कैसी दिखती है?

  • कतार: [Empty]
  • घटना: बटन पर क्लिक करें। घटना के बाद कतार:[Execute OnClick handler(status update, setTimeout() call)]
  • घटना: OnClick हैंडलर में पहली पंक्ति निष्पादित करें (जैसे स्थिति DIV मान बदलें)। घटना के बाद कतार [Execute OnClick handler(which is a setTimeout call), re-draw Status DIV with new "Calculating" value]:।
  • घटना: हैंडलर में दूसरी पंक्ति निष्पादित करें (सेटटाइमआउट कॉल)। के बाद कतार: [re-draw Status DIV with "Calculating" value]। 0 सेकंड के लिए कतार में कुछ भी नया नहीं है।
  • इवेंट: टाइमआउट से अलार्म बजा, 0 सेकंड बाद। के बाद कतार: [re-draw Status DIV with "Calculating" value, execute LongCalc (lines 1-3)]
  • इवेंट: "गणना" मान के साथ स्थिति DIV को फिर से ड्रा करें । के बाद कतार: [execute LongCalc (lines 1-3)]। कृपया ध्यान दें कि यह फिर से ड्रा होने वाली घटना वास्तव में हो सकती है क्योंकि अलार्म बंद हो जाता है, जो ठीक वैसे ही काम करता है।
  • ...

हुर्रे! स्टेटस DIV की गणना शुरू होने से पहले "गणना ..." के लिए अपडेट हो गया !!!



नीचे इन उदाहरणों को दर्शाते हुए JSFiddle का नमूना कोड दिया गया है: http://jsfiddle.net/C2YBE/31/ :

HTML कोड:

<table border=1>
    <tr><td><button id='do'>Do long calc - bad status!</button></td>
        <td><div id='status'>Not Calculating yet.</div></td>
    </tr>
    <tr><td><button id='do_ok'>Do long calc - good status!</button></td>
        <td><div id='status_ok'>Not Calculating yet.</div></td>
    </tr>
</table>

जावास्क्रिप्ट कोड: (पर निष्पादित onDomReadyऔर jQuery 1.9 की आवश्यकता हो सकती है)

function long_running(status_div) {

    var result = 0;
    // Use 1000/700/300 limits in Chrome, 
    //    300/100/100 in IE8, 
    //    1000/500/200 in FireFox
    // I have no idea why identical runtimes fail on diff browsers.
    for (var i = 0; i < 1000; i++) {
        for (var j = 0; j < 700; j++) {
            for (var k = 0; k < 300; k++) {
                result = result + i + j + k;
            }
        }
    }
    $(status_div).text('calculation done');
}

// Assign events to buttons
$('#do').on('click', function () {
    $('#status').text('calculating....');
    long_running('#status');
});

$('#do_ok').on('click', function () {
    $('#status_ok').text('calculating....');
    // This works on IE8. Works in Chrome
    // Does NOT work in FireFox 25 with timeout =0 or =1
    // DOES work in FF if you change timeout from 0 to 500
    window.setTimeout(function (){ long_running('#status_ok') }, 0);
});

12
महान जवाब DVK! यहाँ एक उदाहरण है जो आपके उदाहरण को दिखाता है। gith.github.com/kumikoda/5552511#file-timeout-html
kumikoda

4
वास्तव में अच्छा जवाब, DVK। बस कल्पना करना आसान है, मैंने उस कोड को jsfiddle jsfiddle.net/thangchung/LVAaV
thangchung

4
@ थांगचुंग - मैंने JSFiddle में एक बेहतर संस्करण (2 बटन, प्रत्येक मामले के लिए एक) बनाने की कोशिश की। यह क्रोम और IE पर डेमो के रूप में काम करता है लेकिन किसी कारण से FF पर नहीं - jsfiddle.net/C2YBE/31 देखें । मैंने पूछा कि एफएफ यहां काम क्यों नहीं करता है: stackoverflow.com/questions/20747591/…
DVK

1
@DVK "ब्राउज़र अपने सभी" TODO "कार्य (UI कार्य और जावास्क्रिप्ट आदेश दोनों) को एक ही कतार में होने वाली घटनाओं से उत्पन्न करता है"। सर क्या आप इसके लिए स्रोत प्रदान कर सकते हैं? Imho arent ब्राउज़रों के पास अलग-अलग UI (रेंडरिंग इंजन) और JS थ्रेड्स होने चाहिए .... कोई अपराध नहीं करना चाहिए .... बस सीखना चाहते हैं ..
bhavya_w

1
@ भाव__ नहीं, सब कुछ एक धागे पर होता है। यही कारण है कि एक लंबी js गणना UI को अवरुद्ध कर सकती है
Seba Kerckhof

88

जॉन रिजिग के लेख पर एक नज़र डालें कि कैसे जावास्क्रिप्ट टाइमर काम करता है । जब आप एक टाइमआउट सेट करते हैं, तो यह वास्तव में अतुल्यकालिक कोड को तब तक कतार में लगाता है जब तक इंजन वर्तमान कॉल स्टैक को निष्पादित नहीं करता है।



23

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

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

जब यूआई अपडेट उत्पन्न होता है जब मुख्य धागा व्यस्त होता है, तो कार्य संदेश कतार में जोड़ दिए जाते हैं।

setTimeout(fn, 0);fnइसे क्रियान्वित करने के लिए कतार के अंत में जोड़ें । यह दिए गए समय के बाद संदेश कतार पर जोड़े जाने वाले कार्य को शेड्यूल करता है।


"हर जावास्क्रिप्ट निष्पादन और यूआई अपडेट कार्यों को ब्राउज़र इवेंट कतार सिस्टम में जोड़ा जाता है, फिर उन कार्यों को प्रदर्शन करने के लिए ब्राउज़र मुख्य यूआई थ्रेड में भेजा जाता है।" .... स्रोत कृपया?
bhavya_w

4
उच्च निष्पादन जावास्क्रिप्ट (निकोलस Zakas, Stoyan Stefanov, रॉस हार्मेस, जुलिएन Lecomte, और मैट स्वीनी)
Arley

इस के लिए downvote add this fn to the end of the queue। सबसे महत्वपूर्ण यह है कि वास्तव में setTimeoutइस फंक को कैसे जोड़ा जाता है, इस लूप चक्र का अंत या अगले लूप चक्र की बहुत शुरुआत।
ग्रीन

19

यहाँ परस्पर विरोधी उत्तर हैं, और प्रमाण के बिना यह जानने का कोई तरीका नहीं है कि किस पर विश्वास किया जाए। यहाँ सबूत है कि @dvk सही है और @ साल्वाडोरडाली गलत है। बाद के दावे:

"और यहाँ क्यों है: 0 मिलीसेकंड के एक समय की देरी के साथ सेटटाइमआउट करना संभव नहीं है। न्यूनतम मान ब्राउज़र द्वारा निर्धारित किया जाता है और यह 0 मिलीसेकंड नहीं है। ऐतिहासिक रूप से ब्राउज़र इसे न्यूनतम 10 मिलीसेकंड पर सेट करता है, लेकिन एचटीएमएल 5 चश्मा और। आधुनिक ब्राउज़रों ने इसे 4 मिलीसेकंड पर सेट किया है। "

4ms न्यूनतम टाइमआउट क्या हो रहा है के लिए अप्रासंगिक है। वास्तव में क्या होता है कि सेटटाइमआउट कॉलबैक फ़ंक्शन को निष्पादन कतार के अंत तक धकेलता है। यदि सेटटाइमआउट (कॉलबैक, 0) के बाद आपके पास ब्लॉकिंग कोड है, जिसे चलाने में कई सेकंड लगते हैं, तो कॉलबैक को कई सेकंड तक निष्पादित नहीं किया जाएगा, जब तक कि ब्लॉकिंग कोड समाप्त नहीं हो जाता। इस कोड को आज़माएं:

function testSettimeout0 () {
    var startTime = new Date().getTime()
    console.log('setting timeout 0 callback at ' +sinceStart())
    setTimeout(function(){
        console.log('in timeout callback at ' +sinceStart())
    }, 0)
    console.log('starting blocking loop at ' +sinceStart())
    while (sinceStart() < 3000) {
        continue
    }
    console.log('blocking loop ended at ' +sinceStart())
    return // functions below
    function sinceStart () {
        return new Date().getTime() - startTime
    } // sinceStart
} // testSettimeout0

आउटपुट है:

setting timeout 0 callback at 0
starting blocking loop at 5
blocking loop ended at 3000
in timeout callback at 3033

आपका जवाब एक बात साबित नहीं करता है। यह सिर्फ दिखाता है कि एक विशिष्ट स्थिति में आपके मशीन के तहत कंप्यूटर आपको कुछ संख्याओं को फेंक देता है। संबंधित कुछ साबित करने के लिए आपको कोड की कुछ पंक्तियों और कुछ संख्याओं की तुलना में थोड़ी अधिक आवश्यकता होती है।
साल्वाडोर डाली

6
@ साल्वाडोरदाली, मेरा मानना ​​है कि मेरा प्रमाण अधिकांश लोगों को समझने के लिए पर्याप्त है। मुझे लगता है कि आप रक्षात्मक महसूस कर रहे हैं और इसे समझने का प्रयास नहीं किया है। मुझे इसे स्पष्ट करने का प्रयास करने में खुशी होगी, लेकिन मुझे नहीं पता कि आप क्या समझ रहे हैं। यदि आपको मेरे परिणामों पर संदेह है तो कोड को अपनी मशीन पर चलाने का प्रयास करें।
व्लादिमीर कोर्ना

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

15

ऐसा करने का एक कारण कोड के निष्पादन को एक अलग, बाद के घटना लूप में स्थगित करना है। जब किसी प्रकार के ब्राउज़र इवेंट (उदाहरण के लिए माउस क्लिक) का जवाब दिया जाता है, तो कभी-कभी वर्तमान इवेंट संसाधित होने के बाद ही ऑपरेशन करना आवश्यक होता है। setTimeout()सुविधा यह करने के लिए सबसे आसान तरीका है।

अब संपादित करें कि यह 2015 है मुझे ध्यान देना चाहिए कि यह भी है requestAnimationFrame(), जो बिल्कुल वैसा ही नहीं है, लेकिन यह पर्याप्त रूप से करीब है setTimeout(fn, 0)कि यह ध्यान देने योग्य है।


यह वास्तव में उन स्थानों में से एक है जहां मैंने इसका उपयोग किया है। =)
ज़ैबोट

FYI करें: इस जवाब को यहां stackoverflow.com/questions/4574940/…
Shog9

2
एक अलग, बाद के ईवेंट लूप में कोड के निष्पादन को टालना है : आप बाद के ईवेंट लूप का पता कैसे लगाते हैं ? आप यह कैसे पता लगाते हैं कि वर्तमान घटना लूप क्या है? आपको कैसे पता चलेगा कि आप अब किस इवेंट लूप में हैं?
ग्रीन

@ अच्छी तरह से, तुम सच में नहीं; जावास्क्रिप्ट रनटाइम अप करने के लिए वास्तव में कोई प्रत्यक्ष दृश्यता नहीं है।
पोइंट्टी

RequestAnimationFrame ने आईई और फ़ायरफ़ॉक्स के साथ आईई को कभी भी अपडेट नहीं करने की समस्या का हल किया
डेविड

9

यह पुराने सवालों के साथ एक पुराना सवाल है। मैं इस समस्या पर एक नया रूप जोड़ना चाहता था और जवाब देना चाहता था कि ऐसा क्यों होता है और यह उपयोगी क्यों नहीं है।

तो आपके दो कार्य हैं:

var f1 = function () {    
   setTimeout(function(){
      console.log("f1", "First function call...");
   }, 0);
};

var f2 = function () {
    console.log("f2", "Second call...");
};

और फिर उन्हें निम्नलिखित क्रम में f1(); f2();केवल यह देखने के लिए कॉल करें कि दूसरे ने पहले निष्पादित किया था।

और यहाँ क्यों है: setTimeout0 मिलीसेकंड के एक समय की देरी के साथ होना संभव नहीं है । न्यूनतम मान ब्राउज़र द्वारा निर्धारित किया जाता है और यह 0 मिलीसेकंड नहीं है। ऐतिहासिक रूप से ब्राउज़र्स इसे न्यूनतम 10 मिलीसेकंड पर सेट करते हैं, लेकिन HTML5 चश्मा और आधुनिक ब्राउज़रों ने इसे 4 मिलीसेकंड पर सेट किया है।

यदि घोंसले का स्तर 5 से अधिक है, और टाइमआउट 4 से कम है, तो टाइमआउट को 4 तक बढ़ाएं।

मोज़िला से भी:

आधुनिक ब्राउज़र में 0 एमएस टाइमआउट को लागू करने के लिए, आप यहां वर्णित अनुसार window.postMessage () का उपयोग कर सकते हैं

निम्नलिखित लेख पढ़ने के बाद PS जानकारी ली जाती है ।


1
@ user2407309 क्या आप मजाक कर रहे हैं? आप मतलब है कि HTML5 विनिर्देश गलत है और आप सही हैं? इससे पहले कि आप स्रोत पढ़ें और मजबूत दावे करें। मेरा उत्तर HTML विनिर्देश और ऐतिहासिक रिकॉर्ड पर आधारित है। जवाब देने के बजाय जो बार-बार एक ही सामान को पूरी तरह से समझाता है, मैंने कुछ नया जोड़ा, कुछ ऐसा जो पिछले उत्तरों में नहीं दिखाया गया था। मैं यह नहीं बता रहा हूं कि यह एकमात्र कारण है, मैं सिर्फ कुछ नया दिखा रहा हूं।
साल्वाडोर डाली

1
यह गलत है: "और यहाँ क्यों: 0 मिलीसेकंड के एक समय की देरी के साथ सेटटाइमआउट करना संभव नहीं है।" ऐसा क्यों नहीं है। 4ms देरी setTimeout(fn,0)उपयोगी क्यों है के लिए अप्रासंगिक है।
व्लादिमीर कोर्ना

@ user2407309 इसे "दूसरों द्वारा बताए गए कारणों में जोड़ने के लिए आसानी से संशोधित किया जा सकता है, यह संभव नहीं है ...."। तो यह केवल इस कारण से अपमानजनक है कि विशेष रूप से यदि आप खुद का जवाब कुछ भी नया नहीं बता रहे हैं। बस एक छोटा सा संपादन पर्याप्त होगा।
साल्वाडोर डाली

10
साल्वाडोर डाली: यदि आप यहां माइक्रो फ्लेम वॉर के भावनात्मक पहलुओं को अनदेखा करते हैं, तो आपको शायद यह मानना ​​होगा कि @VladimirKornea सही है। यह सच है कि ब्राउज़र 0ms में 4ms की देरी करते हैं, लेकिन यदि वे नहीं भी करते हैं, तो भी परिणाम समान होंगे। यहां ड्राइविंग तंत्र कॉल कोड के बजाय कतार में धकेल दिया जाता है। इस उत्कृष्ट JSConf प्रस्तुति पर एक नज़र डालें, इससे समस्या को स्पष्ट करने में मदद मिल सकती है: youtube.com/watch?v=8aGhZQkoFbQ
हैशचेंज

1
मैं उलझन में हूँ कि आप ऐसा क्यों सोचते हैं कि न्यूनतम ४ एमएस पर आपका उद्धरण ४ एमएस का वैश्विक न्यूनतम है। HTML5 स्पेक शो से आपकी बोली के रूप में, न्यूनतम 4 एमएस केवल तभी होता है जब आपने नेस्टेड किया हो setTimeout/ setIntervalपांच से अधिक स्तर गहरा हो; यदि आपने नहीं किया है, तो न्यूनतम 0 एमएस है (समय मशीनों की कमी के साथ)। मोज़िला के डॉक्स का विस्तार होता है कि बार-बार कवर करने के लिए, न केवल नेस्टेड मामलों (इसलिए setInterval0 के अंतराल के साथ तुरंत कुछ समय पुनर्निर्धारित किया जाएगा, फिर उसके बाद लंबे समय तक देरी होगी), लेकिन setTimeoutन्यूनतम घोंसले के शिकार के सरल उपयोग को तुरंत कतार में लाने की अनुमति है।
शैडो रेंजर

8

चूँकि इसकी अवधि बीत रही है 0, मुझे लगता है कि इसे पारित करने के लिए setTimeoutनिष्पादन के प्रवाह से कोड हटा दिया गया है । इसलिए यदि यह एक ऐसा कार्य है जिसमें कुछ समय लग सकता है, तो यह बाद के कोड को क्रियान्वित करने से नहीं रोकेगा।


FYI करें: इस उत्तर को यहां stackoverflow.com/questions/4574940/…
Shog9

7

ये दोनों शीर्ष-रेटेड उत्तर गलत हैं। कंसीडर मॉडल और इवेंट लूप पर एमडीएन विवरण देखें , और यह स्पष्ट हो जाना चाहिए कि क्या चल रहा है (एमडीएन संसाधन एक वास्तविक रत्न है)। और बस का उपयोग कर setTimeout इस छोटी सी समस्या को "हल" करने के अलावा अपने कोड में अप्रत्याशित समस्याओं जा सकता है।

वास्तव में क्या है यहाँ पर जा रहा है कि नहीं है "ब्राउज़र पूरी तरह तैयार नहीं हो सकता है अभी तक क्योंकि संगामिति," या के आधार पर कुछ "प्रत्येक पंक्ति एक घटना कतार के पीछे में जुड़ जाता है कि"।

जैसफिल्ड DVK द्वारा प्रदान की वास्तव में एक समस्या को दिखाता है, लेकिन इसके लिए उसका विवरण सही नहीं है।

उसके कोड में क्या हो रहा है कि वह पहले इवेंट हैंडलर को इवेंट में अटैच कर रहा clickहै#do बटन ।

फिर, जब आप वास्तव में बटन पर क्लिक करते हैं, messageतो ईवेंट हैंडलर फ़ंक्शन का संदर्भ देते हुए बनाया जाता है, जिसे जोड़ा जाता है message queue। जब event loopयह संदेश पहुंचता है, तो यह frameस्टैक पर बनाता है , फ़ंक्शन के साथ jsfiddle में क्लिक इवेंट हैंडलर को कॉल करता है।

और यह वह जगह है जहाँ यह दिलचस्प हो जाता है। हम जावास्क्रिप्ट के अतुल्यकालिक होने के बारे में सोच रहे हैं कि हम इस छोटे से तथ्य को नजरअंदाज करने के लिए प्रवण हैं: किसी भी फ्रेम को निष्पादित किया जाना है, अगले फ्रेम से पहले निष्पादित किया जा सकता है । कोई संगति नहीं, लोग।

इसका क्या मतलब है? इसका मतलब यह है कि जब भी संदेश कतार से किसी फ़ंक्शन को आमंत्रित किया जाता है, तो यह कतार को अवरुद्ध कर देता है जब तक कि यह उत्पन्न होने वाले ढेर को खाली नहीं किया जाता है। या, अधिक सामान्य शब्दों में, यह तब तक अवरुद्ध होता है जब तक कि फ़ंक्शन वापस नहीं आया। और यह सब कुछ ब्लॉक कर देता है DOM रेंडरिंग ऑपरेशंस, स्क्रॉलिंग और व्हाट्सएप सहित सभी । यदि आप पुष्टि चाहते हैं, तो फ़ेडल में लंबे समय से चल रहे ऑपरेशन की अवधि बढ़ाने की कोशिश करें (जैसे कि बाहरी लूप को 10 बार और अधिक बार चलाएं), और आप देखेंगे कि जब यह चलता है, तो आप पृष्ठ को स्क्रॉल नहीं कर सकते। यदि यह बहुत लंबा चलता है, तो आपका ब्राउज़र आपसे पूछेगा कि क्या आप इस प्रक्रिया को मारना चाहते हैं, क्योंकि यह पृष्ठ को अनुत्तरदायी बना रहा है। फ़्रेम निष्पादित किया जा रहा है, और इवेंट लूप और संदेश कतार समाप्त होने तक अटके हुए हैं।

तो पाठ का यह साइड-इफेक्ट अपडेट क्यों नहीं कर रहा है? क्योंकि आप जबकि है डोम में तत्व का मान बदल गया है - आप कर सकते हैं console.log()अपने मूल्य तुरंत बदलने के बाद और देखते हैं कि यह है बदल दिया गया है (जो शो क्यों DVK के विवरण सही नहीं है) - ब्राउज़र व्यय करने के लिए ढेर के लिए प्रतीक्षा कर रहा है ( onहैंडलर फ़ंक्शन वापस लौटने के लिए) और इस प्रकार संदेश को समाप्त करने के लिए, ताकि यह अंततः उस संदेश को निष्पादित करने के लिए प्राप्त हो सके जो रनटाइम द्वारा हमारे म्यूटेशन ऑपरेशन की प्रतिक्रिया के रूप में जोड़ा गया है, और यूआई में उस उत्परिवर्तन को प्रतिबिंबित करने के लिए। ।

ऐसा इसलिए है क्योंकि हम वास्तव में कोड खत्म होने का इंतजार कर रहे हैं। हमने यह नहीं कहा है कि "कोई व्यक्ति इसे प्राप्त करता है और फिर परिणाम के साथ इस फ़ंक्शन को बुलाता है, धन्यवाद, और अब मैं इतना imma किया हूं, अब जो कुछ भी करना है," जैसे हम आमतौर पर हमारे घटना-आधारित अतुल्यकालिक जावास्क्रिप्ट के साथ करते हैं। हम एक क्लिक ईवेंट हैंडलर फ़ंक्शन दर्ज करते हैं, हम एक DOM तत्व को अपडेट करते हैं, हम एक अन्य फ़ंक्शन को कॉल करते हैं, दूसरा फ़ंक्शन लंबे समय तक काम करता है और फिर लौटता है, हम फिर उसी DOM तत्व को अपडेट करते हैं, और फिर हम प्रारंभिक फ़ंक्शन से प्रभावी रूप से खाली हो जाते हैं। ढेर। और फिर ब्राउज़र कतार में अगले संदेश को प्राप्त कर सकता है, जो कुछ आंतरिक "ऑन-डोम-म्यूटेशन" प्रकार की घटना को ट्रिगर करके हमारे द्वारा उत्पन्न संदेश हो सकता है।

ब्राउज़र UI तब तक यूआई को अपडेट नहीं कर सकता (या नहीं चुनता है) जब तक कि वर्तमान में निष्पादित फ्रेम पूरा नहीं हो जाता है (फ़ंक्शन वापस आ गया है)। व्यक्तिगत रूप से, मुझे लगता है कि यह प्रतिबंध के बजाय डिजाइन द्वारा है।

setTimeoutफिर काम क्यों करता है ? यह ऐसा करता है, क्योंकि यह प्रभावी ढंग से कॉल को अपने ही फ्रेम से लंबे समय तक चलने वाले फ़ंक्शन को हटा देता है, इसे बाद में windowसंदर्भ में निष्पादित करने के लिए शेड्यूल करता है, ताकि यह स्वयं तुरंत वापस आ सके और संदेश कतार को अन्य संदेशों को संसाधित करने की अनुमति दे सके। और विचार यह है कि UI "अपडेट पर" संदेश जो जावास्क्रिप्ट में हमारे द्वारा ट्रिगर किया गया है जब DOM में पाठ बदलते हुए अब लंबे समय से चल रहे फ़ंक्शन के लिए पंक्तिबद्ध किए गए संदेश से आगे है, ताकि UI अपडेट हमारे ब्लॉक होने से पहले हो जाए लंबे समय के लिए।

ध्यान दें कि a) लंबे समय से चल रहा फ़ंक्शन अभी भी सब कुछ ब्लॉक करता है जब यह चलता है, और b) आपको यह गारंटी नहीं है कि UI अपडेट वास्तव में संदेश कतार में इसके आगे है। मेरे जून 2018 के क्रोम ब्राउजर पर, 0फिडेल द्वारा प्रदर्शित की जाने वाली समस्या को "ठीक" नहीं करता है - 10 करता है। मैं वास्तव में इससे थोड़ा लड़खड़ाया हुआ हूं, क्योंकि यह मेरे लिए तर्कसंगत लगता है कि यूआई अपडेट संदेश को इससे पहले कतारबद्ध किया जाना चाहिए, क्योंकि इसके ट्रिगर को "बाद में" चलाने के लिए लंबे समय से चलने वाले फ़ंक्शन को शेड्यूल करने से पहले निष्पादित किया जाता है। लेकिन शायद V8 इंजन में कुछ अनुकूलन हैं जो हस्तक्षेप कर सकते हैं, या शायद मेरी समझ में बस कमी है।

ठीक है, तो उपयोग करने में क्या समस्या है setTimeout, और इस विशेष मामले के लिए एक बेहतर समाधान क्या है?

सबसे पहले, setTimeoutइस तरह के किसी भी घटना हैंडलर का उपयोग करने के साथ समस्या, एक और समस्या को कम करने की कोशिश करने के लिए, अन्य कोड के साथ गड़बड़ करने का खतरा है। यहाँ मेरे काम से एक वास्तविक जीवन उदाहरण है:

किसी सहकर्मी ने इवेंट लूप पर गलत सूचना दी, setTimeout 0उसके प्रतिपादन के लिए कुछ टेम्प्लेट रेंडरिंग कोड का उपयोग करके "थ्रेड" जावास्क्रिप्ट की कोशिश की । वह अब पूछने के लिए यहां नहीं है, लेकिन मैं यह मान सकता हूं कि शायद उसने प्रतिपादन की गति (जो कि कार्यों की वापसी immediacy होगी) को गेज करने के लिए डाला और पाया कि इस दृष्टिकोण का उपयोग उस फ़ंक्शन से तेजी से तेजी से प्रतिक्रियाओं के लिए करेगा।

पहली समस्या स्पष्ट है; आप जावास्क्रिप्ट को थ्रेड नहीं कर सकते हैं, इसलिए आप यहां कुछ भी नहीं जीतते हैं, जबकि आप ओफिसकेशन जोड़ते हैं। दूसरे, आपने अब संभावित ईवेंट श्रोताओं के ढेर से एक टेम्प्लेट के प्रतिपादन को प्रभावी ढंग से अलग कर लिया है जो उम्मीद कर सकते हैं कि बहुत ही टेम्प्लेट का प्रतिपादन किया गया है, जबकि यह बहुत अच्छी तरह से नहीं हो सकता है। उस फ़ंक्शन का वास्तविक व्यवहार अब गैर-नियतात्मक था, जैसा कि - अनजाने में ऐसा था - कोई भी फ़ंक्शन जो इसे चलाएगा, या इस पर निर्भर करेगा। आप शिक्षित अनुमान लगा सकते हैं, लेकिन आप इसके व्यवहार के लिए ठीक से कोड नहीं कर सकते हैं।

एक नया ईवेंट हैंडलर लिखते समय "फिक्स" जो कि उसके तर्क पर निर्भर था, का भी उपयोग करना था setTimeout 0। लेकिन, यह तय नहीं है, यह समझना मुश्किल है, और यह इस तरह कोड के कारण होने वाली त्रुटियों को डीबग करने में कोई मज़ा नहीं है। कभी-कभी कोई समस्या नहीं होती है, अन्य समय यह लगातार विफल हो जाता है, और फिर फिर कभी-कभी यह काम करता है और छिटपुट रूप से टूटता है, यह मंच के वर्तमान प्रदर्शन पर निर्भर करता है और जो कुछ भी उस समय चल रहा है। यही कारण है कि मैं व्यक्तिगत रूप से इस हैक (यह उपयोग करने के खिलाफ सलाह देंगे है , एक हैक, और हम सभी को पता होना चाहिए यह है कि) जब तक आप वास्तव में पता है कि तुम क्या कर रहे हैं और परिणाम क्या कर रहे हैं।

लेकिन हम इसके बजाय क्या कर सकते हैं? ठीक है, जैसा कि संदर्भित एमडीएन लेख बताता है, या तो काम को कई संदेशों में विभाजित करें (यदि आप कर सकते हैं) ताकि अन्य संदेश जो कतारबद्ध हैं, आपके काम के साथ बातचीत हो सकती है और इसे चलाते समय निष्पादित किया जा सकता है, या एक वेब कार्यकर्ता का उपयोग कर सकता है, जो चल सकता है अपने पृष्ठ के साथ अग्रानुक्रम में और उसकी गणना के साथ किए जाने पर परिणाम लौटाते हैं।

ओह, और अगर आप सोच रहे हैं, "ठीक है, तो क्या मैं इसे अतुल्यकालिक बनाने के लिए लंबे समय तक चलने वाले फ़ंक्शन में कॉलबैक नहीं डाल सकता ?," नहीं। कॉलबैक इसे अतुल्यकालिक नहीं बनाता है, यह स्पष्ट रूप से आपके कॉलबैक को कॉल करने से पहले लंबे समय तक चलने वाला कोड चलाना होगा।


3

दूसरी बात यह है कि फंक्शन इनवोकेशन को स्टैक के निचले भाग पर धकेलें, स्टैक ओवरफ्लो को रोकें यदि आप एक फ़ंक्शन को पुनरावर्ती रूप से बुला रहे हैं। इसमें whileलूप का प्रभाव होता है, लेकिन जावास्क्रिप्ट इंजन को अन्य अतुल्यकालिक टाइमर को आग देता है।


इस के लिए downvote push the function invocation to the bottom of the stack। क्या stackआप के बारे में बात कर रहे हैं अस्पष्ट है। सबसे महत्वपूर्ण यह है कि वास्तव में setTimeoutइस फंक को कैसे जोड़ा जाता है, इस लूप चक्र का अंत या अगले लूप चक्र की बहुत शुरुआत।
ग्रीन

1

सेटटाइमआउट कहकर आप उपयोगकर्ता को जो कुछ भी कर रहे हैं, उस पर प्रतिक्रिया करने के लिए पृष्ठ का समय देते हैं। यह पृष्ठ लोड के दौरान चलने वाले कार्यों के लिए विशेष रूप से सहायक है।


1

कुछ अन्य मामले जहां सेटटाइमआउट उपयोगी है:

आप लंबे समय तक चलने वाले लूप या गणना को छोटे घटकों में तोड़ना चाहते हैं ताकि ब्राउज़र 'फ्रीज' में प्रकट न हो या यह न कहे कि "स्क्रिप्ट ऑन पेज व्यस्त है"।

क्लिक करने पर आप फ़ॉर्म सबमिट बटन को अक्षम करना चाहते हैं, लेकिन यदि आप ऑनक्लियर हैंडलर में बटन को अक्षम करते हैं, तो फ़ॉर्म सबमिट नहीं किया जाएगा। शून्य के समय के साथ सेटटाइमआउट ट्रिक करता है, जिससे ईवेंट समाप्त हो सकता है, फॉर्म सबमिट करना शुरू हो जाता है, फिर आपका बटन अक्षम हो सकता है।


2
अक्षम करना ऑनसुबमिट घटना में बेहतर होगा; यह तेजी से होगा और फॉर्म को तकनीकी रूप से प्रस्तुत किए जाने से पहले कॉल किए जाने की गारंटी होगी क्योंकि आप सबमिट को रोक सकते हैं।
क्रिश

सच सच। मुझे लगता है कि ऑनक्लॉक डिसेबलिंग प्रोटोटाइप के लिए आसान है क्योंकि आप बस बटन में ऑनक्लिक = "this.disabled = true" टाइप कर सकते हैं जबकि सबमिट पर डिसेबल करने के लिए थोड़ा और काम करना पड़ता है।
फेबस्प्रो

1

निष्पादन लूप के बारे में उत्तर और कुछ अन्य कोड पूर्ण होने से पहले DOM को प्रस्तुत करना सही है। जावास्क्रिप्ट में शून्य दूसरा टाइमआउट कोड को छद्म-बहुलित बनाने में मदद करता है, भले ही यह नहीं है।

मैं जोड़ना चाहता हूं कि जावास्क्रिप्ट में क्रॉस ब्राउज़र / क्रॉस प्लेटफॉर्म शून्य-सेकंड टाइमआउट के लिए सबसे अच्छा मूल्य वास्तव में 0 (शून्य) के बजाय लगभग 20 मिलीसेकंड है, क्योंकि कई मोबाइल ब्राउज़र घड़ी की सीमाओं के कारण 20 मिलीसेकंड से छोटे समय रजिस्टर नहीं कर सकते हैं AMD चिप्स पर।

इसके अलावा, लंबे समय से चलने वाली प्रक्रियाएं जिनमें DOM हेरफेर शामिल नहीं है, उन्हें अब वेब वर्कर्स को भेजा जाना चाहिए, क्योंकि वे जावास्क्रिप्ट के सच्चे मल्टीथ्रेडेड निष्पादन प्रदान करते हैं।


2
मैं आपके उत्तर के बारे में थोड़ा उलझन में हूं, लेकिन इसे बढ़ा दिया क्योंकि इसने मुझे ब्राउज़र मानकों पर कुछ अतिरिक्त शोध करने के लिए मजबूर किया। मानकों पर शोध करते समय, मैं हमेशा जहाँ भी जाता हूँ, MDN: developer.mozilla.org/en-US/docs/Web/API/window.setTimeout HTML5 कल्पना 4ms कहता है। यह मोबाइल चिप्स पर घड़ी की सीमाओं के बारे में कुछ नहीं कहता है। जानकारी के स्रोत के लिए अपने बयानों का बैकअप लेने के लिए कठिन समय गुजारना। क्या Google द्वारा डार्ट भाषा को पूरी तरह से हटा दिया गया था, एक टाइमर ऑब्जेक्ट के पक्ष में सेटटाइमआउट हटा दिया गया था।
जॉन ज़ब्रोस्की

8
(...) क्योंकि कई मोबाइल ब्राउज़र घड़ी की सीमाओं के कारण 20 मिलीसेकंड से छोटे टाइमआउट को पंजीकृत नहीं कर सकते हैं (...) प्रत्येक प्लेटफ़ॉर्म की घड़ी के कारण समय सीमाएँ होती हैं और कोई भी प्लेटफ़ॉर्म ठीक 0 सेकंड बाद अगली चीज़ को निष्पादित करने में सक्षम नहीं होता है । वर्तमान वाला। 0ms का टाइमआउट किसी फ़ंक्शन को जल्द से जल्द निष्पादित करने के लिए कहता है और विशिष्ट प्लेटफ़ॉर्म की समय सीमाएं किसी भी तरह से इसका अर्थ नहीं बदलती हैं।
पायोत्र डोब्रोगोस्ट

1

setTimout 0 एक स्थगित वादे की स्थापना के पैटर्न में भी बहुत उपयोगी है, जिसे आप तुरंत वापस करना चाहते हैं:

myObject.prototype.myMethodDeferred = function() {
    var deferredObject = $.Deferred();
    var that = this;  // Because setTimeout won't work right with this
    setTimeout(function() { 
        return myMethodActualWork.call(that, deferredObject);
    }, 0);
    return deferredObject.promise();
}

1

समस्या यह थी कि आप गैर-मौजूदा तत्व पर जावास्क्रिप्ट ऑपरेशन करने की कोशिश कर रहे थे। तत्व को लोड किया जाना बाकी था और setTimeout()एक तत्व को निम्नलिखित तरीकों से लोड करने के लिए अधिक समय दिया गया है:

  1. setTimeout()इस घटना के कारण एसिंक्रोनस होने का कारण बनता है इसलिए सभी सिंक्रोनस कोड के बाद निष्पादित किया जाता है, जिससे आपके तत्व को लोड करने के लिए अधिक समय मिलता है। कॉलबैक जैसे अतुल्यकालिक कॉलबैक ईवेंट कतारsetTimeout() में रखे जाते हैं और सिंक्रोनस कोड के स्टैक खाली होने के बाद इवेंट लूप द्वारा स्टैक पर रखा जाता है।
  2. फ़ंक्शन के दूसरे तर्क के रूप में एमएस के लिए मान 0 setTimeout()अक्सर थोड़ा अधिक होता है (ब्राउज़र के आधार पर 4-10ms)। setTimeout()कॉलबैक को निष्पादित करने के लिए आवश्यक थोड़ा अधिक समय 'टिक्स' की मात्रा के कारण होता है (जहां एक टिक स्टैक पर कॉलबैक को धक्का दे रहा है यदि स्टैक खाली है) इवेंट लूप का। प्रदर्शन और बैटरी जीवन के कारण घटना लूप में टिक्स की मात्रा प्रति सेकंड 1000 बार से कम एक निश्चित राशि तक सीमित होती है ।

-1

जावास्क्रिप्ट सिंगल थ्रेडेड एप्लिकेशन है, ताकि इस घटना को प्राप्त करने के लिए समवर्ती रूप से फ़ंक्शन को चलाने की अनुमति न दें। तो वास्तव में क्या सेटटाइमआउट (fn, 0) ऐसा करता है कि इसका कार्य खोज में हो जाता है जिसे तब निष्पादित किया जाता है जब आपका कॉल स्टैक खाली होता है। मुझे पता है कि यह स्पष्टीकरण बहुत उबाऊ है, इसलिए मैं आपको इस वीडियो के माध्यम से जाने की सलाह देता हूं यह आपकी मदद करेगा कि ब्राउज़र में हुड के तहत चीजें कैसे काम करती हैं। इस वीडियो को देखें: - https://www.youtube.com/watch?time_continue=392&v=8aGhZQkoFbQ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.