2010-01-16 16 views
16

मेरे पास एक वेब एप्लिकेशन है जहां एक टाइमर है जो लगातार गिन रहा है। इस बीच, ग्राहक अक्सर यह देखने के लिए सर्वर के साथ जांच करता है कि टाइमर में अधिक समय जोड़ा गया है या नहीं। कोड इस तरह दिखता है:अजाक्स concurrency

function tick() { 
    // This function is called once every second 
    time -= 1; 
    redisplay(time); 
}; 
function update(newtime) { 
    // This function is called whenever the ajax request 
    // to the server yields a new time 
    time = newtime; 
}; 

यह निश्चित रूप से, एक थोड़ा और अधिक है कि तुलना में जटिल है, लेकिन आप निहित रेस स्थिति देख सकते हैं। क्या होगा यदि अद्यतन और टिक फ़ंक्शन दोनों एक ही समय में time को संशोधित करने का प्रयास कर रहे हैं?

सचमुच, मुझे इस तरह के समेकन मुद्दे से निपटने के तरीके के बारे में समझने के लिए लगभग पर्याप्त जावास्क्रिप्ट नहीं पता: क्या ऐसा करने का कोई आसान तरीका है, या यदि नहीं, तो क्या कोई मुझे उन संसाधनों के प्रति इंगित कर सकता है जहां मैं और जान सकता हूं ?

धन्यवाद।

+0

हमेशा इस सवाल से पूछना चाहता था। – zedoo

+1

बहुत अच्छा सवाल! –

+1

बस स्पष्टता के लिए, क्या यह कोड ब्राउज़र में चल रहा है, या सर्वर पर node.js जैसे किसी सर्वर पर चल रहा है? –

उत्तर

16

आपके पास दौड़ की स्थिति नहीं है, क्योंकि जावास्क्रिप्ट एक साथ निष्पादित नहीं करता है।

हर बार जब कॉलबैक को एसिंक ऑपरेशन (AJAX, setTimeout, आदि) से निकाल दिया जाता है, तो कॉलबैक को अन्य एसिंक ऑपरेशन से दूसरे कॉलबैक से पहले निष्पादित करना होगा। तो यदि update() चल रहा है, तो कोई अन्य जावास्क्रिप्ट नहीं है। एक बार update() समाप्त हो जाने पर, एसिंक ऑपरेशंस से अन्य कॉलबैक निकाल दिए जा सकते हैं (उदाहरण के लिए, tick())। दिलचस्प बात यह है कि यह भी है कि setTimeout और इसके जैसे समय समाप्ति पर सटीक पल पर निष्पादित करने की गारंटी नहीं है: कुछ अन्य जावास्क्रिप्ट कॉलबैक के निष्पादन को अवरुद्ध कर सकता है।

यह सब कुछ कैसे काम करता है इस बारे में कुछ अच्छी जानकारी के लिए http://ejohn.org/blog/how-javascript-timers-work/ देखें।

-2

जब तक आप वर्तमान समय में कुछ और सेकंड जोड़ते हैं तो आपको ठीक होना चाहिए।

time = newtime; करने के बजाय time += newtime; आजमाएं इस तरह आप जिस दूसरे से चिंतित हैं उसे खोना नहीं होगा।

फिर भी, आप केवल सबसे खराब में दूसरे स्थान पर हैं।

+0

नोट, नया समय बस जोड़ने के लिए कितना अधिक समय है। –

+5

मुझे नहीं लगता कि यह दौड़ स्थिति समस्या –

0

मैं गलत था: इससे समस्या हल नहीं होती है! (कोड के बाद explaination)

NEWTIME = false; 
function tick() { 
    // This function is called once every second 
    if (NEWTIME) { 
     time = NEWTIME; 
     NEWTIME = false; 
    } 
    time -= 1; 
    redisplay(time); 
}; 
function update(newtime) { 
    // This function is called whenever the ajax request 
    // to the server yields a new time 
    NEWTIME = newtime; 
}; 

यह गलत समाधान के साथ समस्या यह है कि इस तरह से आप बस चर NEWTIME चर time से रेस स्थिति मुद्दा ले जाने के कर।

बस इस लगता है: tick पहुँच के निष्पादन और अब लाइन time = NEWTIME; कार्यान्वित करता है, सतत, कहा जाता हो अपडेट से पहले और NEWTIME एक मूल्य X हो जाता है। अब निष्पादन निष्पादन NEWTIME = false; निष्पादित जारी है। इस तरह आपने XNEWTIME का मूल्य खो दिया है और इसलिए अपडेट() कॉल का प्रभाव!

+0

को संबोधित करता है यह वही है जो मैं करना चाहता था, यह दौड़ की स्थिति को कैसे संबोधित नहीं करता है? आप एक चक्र से दूर हो सकते हैं, लेकिन ऐसा लगता है कि 'NEWTIME' खो जाएगा। –

+0

@ जस्टिन इस तरह आप रेस कंडीशन इश्यू को वैरिएबल 'टाइम' से वैरिएबल' न्यूटीएमई 'में ले जाते हैं। बस इस लगता है: टिक के निष्पादन तक पहुँचता है और कार्यान्वित लाइन समय = Newtime ';' अब, जारी, इससे पहले कि 'कहा जाता हो update' और' NEWTIME' मान 'X' हो जाता है। अब 'टिक' निष्पादन 'NEWTIME = false;' निष्पादित करना जारी रखता है। इस तरह आपने 'अपडेट()' कॉल का प्रभाव खो दिया है! –

+0

हां, लेकिन आप केवल अधिकतम एक टिक के लिए इसे खो देते हैं, क्योंकि मूल तरीके के विपरीत जो हमेशा के लिए खो जाता है * अगर * भाषा समवर्ती थी। –

-1

समस्या को कुछ सेमेफोर की आवश्यकता है। मैं पिछले एक खत्म होने के बाद AJAX भेजने के लिए बहुत कुछ करता हूं। आपका मामला थोड़ा सा है;)

ऐसा कुछ करने का प्रयास करें। यह AJAX कॉलबैक के साथ टकराने के समय के सभी प्रयासों को अनदेखा करना चाहिए।

window.TimeKeeper = new function(){ 
this.time=0; //initial value, whatever 
this.isopen=true; 

this.decrement = function(){ 
if(this.isopen){ 
    this.time--; 
    redisplay(this.time); 
    } 
} 
this.set = function(val){ 
if(this.isopen){ 
    this.isopen=false; 
    this.time=val; 
    this.isopen=true; 
    } else { 
    //another AJAX callback is modifying time. 
    //You can enqueue current value and put it later 
    } 
} 

} 

function tick() { 
    TimeKeeper.decrement(); 

}; 
function update(newtime) { 
    TimeKeeper.set(newtime); 
}; 

एक और बात - setTimeout एक नया धागे की तरह काम करता है और मैं उम्मीद होती है कि ब्राउज़र को सिंक्रनाइज़ मेम पहुँच करते हैं, तो यह करता है, तो मूल्य decrementing से पहले वृद्धि नहीं हुई जांच करने के लिए पर्याप्त हो सकता है। लेकिन उपर्युक्त समाधान अधिक लचीला और सुरक्षित है।

और एक छोटे से टिप - भी अक्सर AJAX के द्वारा क्वेरी से बचने - यह अतिरिक्त समस्याएँ हो सकती हैं - भिन्न क्रम में वापस आ रहा अनुरोध भेजा है, और फ़ायरफ़ॉक्स स्मृति उपयोग बहुत ज्यादा ajax एक मिनट पर बहुत कुछ के निर्माण से की तरह;)

+0

धन्यवाद। क्या होता है अगर कमी विफल हो जाती है, यद्यपि? समय फिर से नहीं चलाया जाता है। इस मामले में, आप केवल रेडिसप्ले कॉल को बाहर के बाहर ले जा सकते हैं, लेकिन अधिक सामान्य मामले के लिए, क्या प्रतीक्षा करने और एक पल में फिर से प्रयास करने का एक गैर-अवरुद्ध तरीका है? इसके अलावा, मुझे सर्वर से अपडेट के लिए काफी बार जांचना होगा, इस समय इसका मतलब है कि मैं प्रति सेकंड एक AJAX कॉल कर रहा हूं। अगर मुझे अक्सर अपडेट की ज़रूरत है, तो क्या यह AJAX से ऐसा करने का एक बेहतर तरीका है? जब कोई ईवेंट होता है तो सर्वर के लिए सर्वर को नोटिस भेजने का कोई तरीका नहीं है, है ना? – So8res

+0

मेरे पास गहराई से जांच करने के लिए समय नहीं है, लेकिन यह मेरे लिए एक अच्छा समाधान प्रतीत नहीं होता है ... –

+2

जावास्क्रिप्ट एकल धागा है। आपको सेमफोर की आवश्यकता नहीं है। सबसे बुरा यह होता है कि कमी होती है (redisplay के बाद), और उसके बाद मूल्य अद्यतन से एक नए आपूर्ति मूल्य द्वारा तुरंत अधिलेखित किया जाता है। उस स्थिति में, समय कम हो जाएगा और बाद में प्रदर्शित किया जाएगा। एक समस्या नहीं है। – PanCrit

8

जावास्क्रिप्ट एकल धागा है। कोई दौड़ की स्थिति नहीं है। निष्पादन के दौरान ओवरलैप करने के लिए दो पंक्तियों time = newtime; और time -= 1; के लिए जावास्क्रिप्ट में कोई तरीका नहीं है। वास्तव में, दो कार्यों की गारंटी है कि ओवरलैप न करें। उनमें से एक भाग जाएगा और फिर दूसरा भाग जाएगा।