नोड.जेएस कॉलबैक पिरामिड से निपटना


9

मैंने अभी नोड का उपयोग करना शुरू किया है, और एक चीज जो मैंने जल्दी से देखी है कि कॉलबैक कितनी जल्दी इंडेंटेशन का मूर्खतापूर्ण स्तर तक निर्माण कर सकता है:

doStuff(arg1, arg2, function(err, result) {
    doMoreStuff(arg3, arg4, function(err, result) {
        doEvenMoreStuff(arg5, arg6, function(err, result) {
            omgHowDidIGetHere();
        });
    });
});

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

क्या यहाँ मदद करने के लिए फंक्शन स्कोप का उपयोग करना ठीक है? उन सभी कॉलबैक फ़ंक्शंस को रखें, जो किसी फ़ंक्शन के अंदर एक वैश्विक-ईश ऑब्जेक्ट तक पहुंच की आवश्यकता होती है, जो उस ऑब्जेक्ट को घोषित करता है, इसलिए यह एक क्लोजर में जाता है?

function topLevelFunction(globalishObject, callback) {

    function doMoreStuffImpl(err, result) {
        doMoreStuff(arg5, arg6, function(err, result) {
            callback(null, globalishObject);
        });
    }

    doStuff(arg1, arg2, doMoreStuffImpl);
}

और इतने पर कई और परतों के लिए ...

या हर एक कॉलबैक के लिए एक नामित फ़ंक्शन घोषित किए बिना इंडेंटेशन के स्तर को कम करने में मदद करने के लिए फ्रेमवर्क आदि हैं? आप कॉलबैक पिरामिड से कैसे निपटेंगे?


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

जवाबों:


7

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

"वादे" के कई कार्यान्वयन हैं:


उदाहरण के लिए आप इस नेस्टेड कॉलबैक को फिर से लिख सकते हैं

http.get(url.parse("http://test.com/"), function(res) {
    console.log(res.statusCode);
    http.get(url.parse(res.headers["location"]), function(res) {
        console.log(res.statusCode);
    });
});

पसंद

httpGet(url.parse("http://test.com/")).then(function (res) {
    console.log(res.statusCode);
    return httpGet(url.parse(res.headers["location"]));
}).then(function (res) {
    console.log(res.statusCode);
});

कॉलबैक में कॉलबैक के बजाय a(b(c()))आप ".then" को चेन करें a().then(b()).then(c())


यहाँ एक परिचय: http://howtonode.org/promises


क्या आप इन संसाधनों पर क्या करते हैं और इस बारे में अधिक जानकारी देने के लिए क्या कहेंगे? "लिंक-ओनली जवाब" का स्टैक एक्सचेंज में बहुत स्वागत नहीं है
gnat

1
ठीक है माफ़ कर दो। मैंने एक उदाहरण और अधिक जानकारी जोड़ी है।
फाबिएन सा

3

वादों के विकल्प के रूप में आपको जनरेटर कार्यों केyield संयोजन में कीवर्ड पर एक नजर डालनी चाहिए जिसे EcmaScript 6 में पेश किया जाएगा। दोनों आज Node.js 0.11.x बिल्ड में उपलब्ध हैं, लेकिन आवश्यकता है कि आप नोड चलाते समय ध्वज को अतिरिक्त रूप से निर्दिष्ट करें .js:--harmony

$ node --harmony app.js

उन निर्माणों और एक पुस्तकालय जैसे कि टीजे होलोवैचुक के सह का उपयोग करना आपको एक शैली में अतुल्यकालिक कोड लिखने की अनुमति देता है जो तुल्यकालिक कोड की तरह दिखता है , हालांकि यह अभी भी एक अतुल्यकालिक तरीके से चलता है। मूल रूप से, ये चीजें Node.js. के लिए सह-दिनचर्या समर्थन को लागू करती हैं

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

var run = function * () {
  var data = yield doSomethingAsync();
  console.log(data);
};

इस जनरेटर फ़ंक्शन को चलाने के लिए आपको पहले से उल्लेखित सह जैसे पुस्तकालय की आवश्यकता होती है। कॉल तब दिखता है:

co(run);

या, इसे इनलाइन करने के लिए:

co(function * () {
  // ...
});

कृपया ध्यान दें कि जनरेटर कार्यों से आप अन्य जनरेटर कार्यों को कॉल कर सकते हैं, आपको केवल उन्हें yieldफिर से उपसर्ग करने की आवश्यकता है ।

इस विषय के लिए एक परिचय के लिए, Google को ऐसे शब्दों के लिए yield generators es6 async nodejsखोजें और आपको बहुत सारी जानकारी मिलनी चाहिए। इसकी आदत पड़ने में थोड़ा समय लगता है, लेकिन एक बार जब आप इसे प्राप्त कर लेते हैं, तो आप कभी वापस नहीं जाना चाहते हैं।

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

गुड लक और मजा करें :-)!


0

अब आप पैकेज है asyncawait क्या होना चाहिए करने के लिए एक बहुत करीबी वाक्य रचना के साथ, भविष्य देशी समर्थन की awaitऔर asyncनोड में।

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

अभी भी कॉलम नरक / कयामत दुःस्वप्न के पिरामिड से बाहर निकलने के लिए एक अच्छा विकल्प है, जब प्रदर्शन प्राथमिक चिंता नहीं है और जहां तुल्यकालिक लेखन शैली आपकी परियोजना की आवश्यकताओं के अनुरूप है।

पैकेज डॉक्टर से मूल उदाहरण:

var foo = async (function() {
    var resultA = await (firstAsyncCall());
    var resultB = await (secondAsyncCallUsing(resultA));
    var resultC = await (thirdAsyncCallUsing(resultB));
    return doSomethingWith(resultC);
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.