2013-03-28 5 views
6

मुझे एसिंक ऑपरेशंस का उपयोग करके विशिष्ट नोड्स पर संचालन करने के लिए एक पेड़ पर पुनर्विचार करने की आवश्यकता है। मैं प्रवाह को कैसे नियंत्रित कर सकता हूं ताकि जब यह हो जाए तो मेरे पास नोड्स तक पहुंच हो? मैं एक समारोह जो लक्ष्य यह पेड़ के माध्यम से पुनरावृति और सभी के नाम के साथ 'प' शुरू फायदा उठाने में है हैजावास्क्रिप्ट: एसिंक रिकर्सिव पेड़ ट्रैवर्सल के साथ प्रवाह को कैसे नियंत्रित करें?

data = { 
    name: "deven", 
    children: [ 
    { name: "andrew" }, 
    { name: "donovan" }, 
    { name: "james", 
     children: [ 
     { name: "donatello" }, 
     { name: "dan" } 
     ] 
    }, 
    { name: "jimmy", 
     children: [ 
     { name: "mike" }, 
     { name: "dank" } 
     ] 
    } 
    ] 
}; 

:

यहाँ एक उदाहरण की स्थिति है। बाद में, मैं एक और समारोह में पेड़ पारित करने के लिए कुछ और काम करने के लिए (संभवतः एक ऐसा नाम है जो 'एक' के साथ शुरू होता है कि सभी नोड्स हटाना), लेकिन केवल तब प्रारंभिक प्रसंस्करण किया गया है चाहता हूँ:

function capitalize_d(node) { 
    if(node.name === "d") { 
     node.name = node.name.toUpperCase(); 
    } 

    if(node.children != null) { 
     for(var i = 0; i < node.children.length; i++) { 
      capitalize_d(node.children[i]); 
     } 
    } 
} 

function remove_a(node) { 
} 

capitalize_d(data); 

// Should only get called after all the d's have been capitalized. 
remove_a(data); 

उपर्युक्त कोड ठीक काम करता है, क्योंकि capitalize_d अवरुद्ध है। यदि capitalize_d असीमित रूप से पुनरावर्ती है, तो हम remove_a को यह करने के बाद कैसे कॉल कर सकते हैं? setTimeoutcapitalize_d पर कॉल करें।

function capitalize_d(node) { 
    setTimeout(function() { 

     if(node.name === "d") { 
      node.name = node.name.toUpperCase(); 
     } 

     if(node.children != null) { 
      for(var i = 0; i < node.children.length; i++) { 
       capitalize_d(node.children[i]); 
      } 
     } 

    }, 1); 
} 

function remove_a(node) { 
} 

capitalize_d(data); 

// Should only get called after all the d's have been capitalized. 
remove_a(data); 

समस्या हम पेड़ सभी एक ही समय में बंद निकाल दिया हो रही की विभिन्न शाखाओं के लिए प्रसंस्करण है है, और यह जब यह अंत में पेड़ संसाधित किया जाना पूर्ण बताने के लिए असंभव है।

मैं इसे कैसे हल कर सकता हूं?

उत्तर

3

मुझे संक्षेप में प्रस्तुत क्या मैं अपनी आवश्यकताओं की समझ में आ करते हैं:

  • आप एक डेटा पेड़ जहां प्रत्येक एकल नोड परिचालन (capitalize_d और अपने उदाहरण में remove_a) का एक सेट से एसिंक्रोनस रूप से बदला जा सकता है है,
  • आप यह सुनिश्चित करना चाहते हैं कि अगले एक को अनुमति देने से पहले प्रत्येक एकल नोड को किसी दिए गए ऑपरेशन के अधीन किया गया हो।

मैं 10 साल या उससे अधिक खर्च किया है वास्तविक समय एम्बेडेड सॉफ्टवेयर को डिजाइन करने, और मुझे विश्वास है, इस क्षेत्र में आवश्यकताओं meaner और कुछ भी सबसे नेटवर्क प्रोग्रामर अपने पूरे जीवन में अनुभव होगा की तुलना में scarrier हैं। यह आपको चेतावनी देता है कि आपको यहां गंभीर रूप से गलत तरीके से नेतृत्व किया जा रहा है।

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

दूसरे शब्दों में, आप हाथ में तीन कार्यों है:

  • एक डाटा अधिग्रहण प्रक्रिया है कि नोड्स एसिंक्रोनस रूप
  • एक डेटा उत्पादन प्रक्रिया एकत्रित करेगा कि एक सुसंगत, परिष्कृत डेटा पेड़ पेश करेंगे
  • एक नियंत्रक प्रक्रिया जो डेटा अधिग्रहण और उत्पादन को सिंक्रनाइज़ करेगी (संभवतः सीधे उपयोगकर्ता इंटरफ़ेस यदि उपरोक्त दो प्रक्रियाएं काफी स्मार्ट हैं, लेकिन इस पर भरोसा न करें)।

मेरी सलाह: एक ही समय में अधिग्रहण और उत्पादन करने की कोशिश नहीं करते।

बस आपको बुरा सपना की एक विचार देने के लिए आप के लिए जा रहे हैं:

  • कैसे संचालन ट्रिगर कर रहे हैं पर निर्भर करता है, वहाँ एक संभावना है कि पेड़ कभी नहीं पूरी तरह से किसी दिए गए आपरेशन द्वारा कार्रवाई की जाएगी है । मान लीजिए कि नियंत्रण सॉफ्टवेयर में कुछ नोड्स पर capitalize_d कॉल करने के लिए भूल जाता है, remove_a बस कभी नहीं हरी बत्ती

  • इसके विपरीत मिल जाएगा, अगर आप यादृच्छिक पर पेड़ पर गोली, ऐसा लगता है कि कुछ नोड्स कई बार कार्रवाई की जाएगी बहुत संभावना है , जब तक आप एक ही परिवर्तन एक दिया नोड

  • के लिए दो बार आवेदन करने के लिए यदि आप remove_a प्रसंस्करण कभी शुरू करना चाहते हैं को रोकने के लिए आपरेशन कवरेज का ट्रैक रखने के लिए, आप किसी भी अधिक capitalize_d अनुरोध भेजने से नियंत्रित सॉफ्टवेयर को रोकने के लिए हो सकता है, या अन्यथा प्रकाश हमेशा के लिए लाल रंग में रह सकता है। आप अपने अनुरोधों पर एक तरफ या दूसरे प्रवाह पर प्रवाह नियंत्रण समाप्त कर देंगे (या बदतर: आप कोई भी नहीं करेंगे, और आपका सिस्टम मौत को स्थिर करने की संभावना होगी, ऑपरेशन प्रवाह उस मौके स्थान से दूर हो जाए जो आपको मौके से मारा जाता है)।

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

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

मुझे लगता है कि आप इसे पोस्ट कर रहे हैं यहां सवाल यह है कि आप वास्तव में ऐसा नहीं करना चाहते हैं। अब यदि आप बॉस करते हैं, तो, एक प्रसिद्ध एंड्रॉइड उद्धृत करने के लिए, मैं आपकी संभावनाओं के बारे में आपसे झूठ नहीं बोल सकता, लेकिन ... आप मेरी सहानुभूति रखते हैं।

अब गंभीरता से लोग .. इस तरह से मैं समस्या से निपटने का तरीका हूं।

1) समय में एक भी बिंदु पर अपने डेटा का एक स्नैपशॉट ले

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

2) स्नैपशॉट के साथ पेड़ का निर्माण, और फिर लागू जो कुछ capitalize_d, remove_a और camelize_z संचालन क्रमिक रूप से इस दिए गए स्नैपशॉट पर।

समानांतर में, डेटा अधिग्रहण प्रक्रिया नए नोड्स एकत्रित करना या मौजूदा स्नैपशॉट लेने के लिए तैयार मौजूदा अपडेट को अपडेट करना जारी रखेगी।

इसके अलावा, आप अपने कुछ प्रसंस्करण को आगे बढ़ा सकते हैं। स्पष्ट रूप से capitalize_d वृक्ष संरचना का कोई लाभ नहीं लेता है, इसलिए पेड़ के निर्माण से पहले स्नैपशॉट में प्रत्येक नोड में capitalize_d लागू कर सकते हैं। आप पहले भी कुछ परिवर्तनों को लागू करने में सक्षम हो सकते हैं, यानी प्रत्येक एकत्रित नमूने पर। यह आपको बहुत अधिक प्रोसेसिंग समय और कोड जटिलता बचा सकता है।

theroretical प्रलाप का एक सा के साथ समाप्त करने के लिए

,

  • अपने दृष्टिकोण
  • मेरे दृष्टिकोण है, डेटा पेड़ एक साझा उद्देश्य यह है कि डाटा अधिग्रहण और डेटा उत्पादन प्रक्रियाओं से समवर्ती acces का समर्थन करना चाहिए पर विचार करना है डेटा अधिग्रहण प्रक्रिया को डेटा उत्पादन प्रक्रिया में डेटा के लगातार सेट (असीमित रूप से) करने के लिए, जो अनुक्रमिक रूप से डेटा के निर्धारित सेट को संभाल सकता है।

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

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

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

सिद्धांत रूप में, मेरा दृष्टिकोण कुछ प्रतिक्रियाशीलता खो देगा, क्योंकि संसाधित डेटा थोड़ा पुराना हो जाएगा, लेकिन समवर्ती पहुंच दृष्टिकोण का परिणाम शायद धीमे सॉफ़्टवेयर (और निश्चित रूप से 5-10 गुना बड़ा और उग्र) होगा।

1

मैं जानता हूँ कि इस पोस्ट पुरानी है, लेकिन यह खोज परिणामों में आया, और अकेला प्रतिक्रिया एक काम उदाहरण प्रदान नहीं करता है, तो यहाँ कुछ मैं हाल ही में किया था का एक संशोधित संस्करण है ...

function processTree(rootNode, onComplete) { 

    // Count of outstanding requests. 
    // Upon a return of any request, 
    // if this count is zero, we know we're done. 
    var outstandingRequests = 0; 

    // A list of processed nodes, 
    // which is used to handle artifacts 
    // of non-tree graphs (cycles, etc). 
    // Technically, since we're processing a "tree", 
    // this logic isn't needed, and could be 
    // completely removed. 
    // 
    // ... but this also gives us something to inspect 
    // in the sample test code. :) 
    var processedNodes = []; 

    function markRequestStart() { 
     outstandingRequests++; 
    } 

    function markRequestComplete() { 
     outstandingRequests--; 
     // We're done, let's execute the overall callback 
     if (outstandingRequests < 1) { onComplete(processedNodes); } 
    } 

    function processNode(node) { 
     // Kickoff request for this node 
     markRequestStart(); 
     // (We use a regular HTTP GET request as a 
     // stand-in for any asynchronous action) 
     jQuery.get("/?uid="+node.uid, function(data) { 
      processedNodes[node.uid] = data; 
     }).fail(function() { 
      console.log("Request failed!"); 
     }).always(function() { 
      // When the request returns: 
      // 1) Mark it as complete in the ref count 
      // 2) Execute the overall callback if the ref count hits zero 
      markRequestComplete(); 
     }); 

     // Recursively process all child nodes (kicking off requests for each) 
     node.children.forEach(function (childNode) { 
      // Only process nodes not already processed 
      // (only happens for non-tree graphs, 
      // which could include cycles or multi-parent nodes) 
      if (processedNodes.indexOf(childNode.uid) < 0) { 
       processNode(childNode); 
      } 
     }); 

    } 

    processNode(rootNode); 
} 

और यहां क्विनिट का उपयोग करके उदाहरण का उपयोग किया गया है:

QUnit.test("async-example", function(assert) { 
    var done = assert.async(); 

    var root = { 
     uid: "Root", 
     children: [{ 
      uid: "Node A", 
      children: [{ 
       uid: "Node A.A", 
       children: [] 
      }] 
     },{ 
      uid: "Node B", 
      children: [] 
     }] 
    }; 

    processTree(root, function(processedNodes) { 
     assert.equal(Object.keys(processedNodes).length, 4); 
     assert.ok(processedNodes['Root']); 
     assert.ok(processedNodes['Node A']); 
     assert.ok(processedNodes['Node A.A']); 
     assert.ok(processedNodes['Node B']); 
     done(); 
    }); 
}); 
संबंधित मुद्दे