2012-10-13 19 views
9

काम नहीं कर रहा, कुछ इस तरह लेखन:Node.js: जबकि पाश कॉलबैक यह जानते हुए कि जबकि Node.js एसिंक्रोनस रूप से काम कर रहा है के रूप में की उम्मीद

function sleep() { 
    var stop = new Date().getTime(); 
    while(new Date().getTime < stop + 15000) { 
     ; 
    } 
} 

sleep(); 
console.log("done"); 

... नींद() कहेंगे, के लिए सर्वर को ब्लॉक जबकि लूप (15secs) की अवधि और फिर कंसोल पर "किया" प्रिंट करें। जहां तक ​​मैं समझता हूं, ऐसा इसलिए है क्योंकि Node.js जावास्क्रिप्ट को केवल मुख्य धागे तक पहुंच प्रदान कर रहा है, और इसलिए इस चीज का बच्चा आगे निष्पादन को रोक देगा।

तो मैं समझता हूँ कि इस का हल कॉलबैक उपयोग करने के लिए है:

function sleep(callback) { 
    var stop = new Date().getTime(); 
    while(new Date().getTime() < stop + 15000) { 
     ; 
    } 
    callback(); 
} 

sleep(function() { 
    console.log("done sleeping"); 
}); 

console.log("DONE"); 

तो मैंने सोचा कि यह 'पूर्ण' मुद्रित होता है और 15 सेकेंड के बाद। 'नींद आ रही है', क्योंकि नींद() फ़ंक्शन को कॉल किया जाता है और कॉलबैक फ़ंक्शन में पॉइंटर दिया जाता है। हालांकि यह फ़ंक्शन काम कर रहा है (जबकि लूप), अंतिम पंक्ति निष्पादित की जाएगी (मुद्रित 'किया गया')। 15 सेकंड के बाद, जब नींद() फ़ंक्शन समाप्त हो जाती है, तो वह दिए गए कॉलबैक फ़ंक्शन को कॉल करती है, जो तब 'नींद की नींद' प्रिंट करती है।

स्पष्ट रूप से मैं यहां कुछ गलत समझ गया, क्योंकि उपरोक्त दोनों तरीकों से अवरुद्ध है। क्या कोई कृपया स्पष्टीकरण दे सकता है?

अग्रिम धन्यवाद, Slagjoeyoco

उत्तर

13

जावास्क्रिप्ट और Node.js एकल लड़ी है, जो एक सरल while ब्लॉक का मतलब कर रहे हैं; while ब्लॉक होने तक कोई अनुरोध/ईवेंट संसाधित नहीं किया जा सकता है। कॉलबैक इस समस्या को जादुई रूप से हल नहीं करते हैं, वे सिर्फ एक फ़ंक्शन में कस्टम कोड पास करने में मदद करते हैं। इसके बजाय, process.nextTick, जो आप esentially एक ही परिणाम दे लेकिन अनुरोध और घटनाओं के लिए अंतरिक्ष छोड़ देता है और साथ ही यानी संसाधित करने के लिए, का उपयोग कर पुनरावृति, यह ब्लॉक नहीं करता:

function doSleep(callback) { 
    var stop = new Date().getTime(); 

    process.nextTick(function() { 
     if(new Date().getTime() < stop + 15000) { 
      //Done, run callback 
      if(typeof callback == "function") { 
       callback(); 
      } 
     } else { 
      //Not done, keep looping 
      process.nextTick(arguments.callee); 
     } 
    }); 
} 

doSleep(function() { 
    console.log("done sleeping"); 
    console.log("DONE"); 
}); 
+0

आप अपने आप को उलझी रहे हैं। एक सरल सेटटाइमआउट (कॉलबैक, देरी) को अतुल्यकालिक रूप से निर्देशित करने के लिए पर्याप्त होना चाहिए। –

+4

@ FabiánH.jr। मुद्दा यह है कि ओपी को यह समझने में दिलचस्पी हो सकती है कि उसका 'समय' क्यों काम नहीं कर रहा है और एक गैर-अवरुद्ध तरीके से 'जबकि' लिखा जा सकता है, जो कि इम्हो थोडा बेहतर है "इससे आपकी कोई फर्क नहीं पड़ता काम नहीं करता है, इसे इसके बजाय अन्य तरीके से करें "। – Mahn

+0

अच्छी तरह से सच, महान उत्तर समग्र और अब जब आप इसका उल्लेख करते हैं तो यह node.js की आंतरिक प्रक्रिया में काफी अंतर्दृष्टिपूर्ण था –

2

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

वास्तविक समाधान किसी अन्य धागे पर व्यस्त लूप के बजाय setTimeout का उपयोग करना है।

9

आप तुरंत sleep पर कॉल कर रहे हैं, और नया sleep फ़ंक्शन ब्लॉक। जब तक स्थिति पूरी नहीं हो जाती तब तक यह फिर से चलती रहती है। आप अवरुद्ध से बचने के लिए setTimeout() उपयोग करना चाहिए:

setTimeout(function() { 
    console.log('done sleeping'); 
}, 15000); 
0

जैसा कि पहले ही उल्लेख किया है, अतुल्यकालिक निष्पादन setTimeout के द्वारा प्राप्त किया जाना चाहिए() के बजाय, जबकि से, क्योंकि, जबकि एक "निष्पादन फ्रेम" में फ्रीज होगा।

यह भी लगता है कि आपके उदाहरण में वाक्यविन्यास त्रुटि है।

यह एक ठीक काम करता है: http://jsfiddle.net/6TP76/