2015-01-16 9 views
7

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

हालांकि, जब आपके पास कॉलबैक की कई परतें होती हैं जहां कई कॉलबैक निष्पादित मार्गों के समान होते हैं, तो आप अलग-अलग कॉलबैक श्रृंखलाओं में बहुत से कॉलबैक कोड को फिर से लिखते हैं। उदाहरण के लिए, यदि नीचे mycb1 और mycb2 परिभाषाएं ए के बाहर स्थानांतरित की जाती हैं, तो उनके पास अब ए के चर के लिए अंतर्निहित पहुंच नहीं है और इस प्रकार, अब बंद होने के रूप में कार्य नहीं करते हैं।

एम्बेडेड परिभाषाओं के साथ उदाहरण जहां वे बंद होने के रूप में कार्य करते हैं।

mod.A=function(){ 
    var mycb1=function(err){ 
    if (!err){ 
     var mycb2=function(err){ 
     cb(err); 
     }; 
     mod.foo2(args,mycb2); 
    } 
    else{cb(err);} 
    }; 
    mod.foo1(args,mycb1); 
} 

mod.foo1 = function(args,cb){ 
    //do some work 
    cb(err); 
}; 

mod.foo2 = function(args,cb){ 
    //do some work 
    cb(err); 
} 
//execute 
mod.A(); 

मैं तो निम्न कार्य करें, लेकिन अभी वे जहां कभी वे कहा जाता है से बंद के रूप में इस्तेमाल किया जा सकता mycb1 और mycb2 कार्यों के लिए चर गुंजाइश को बदलने में सक्षम होना चाहता हूँ। उदाहरण के लिए:

var mycb2=function(err){ 
    ... 
    cb(err); 
}; 

var mycb1=function(err){ 
    if (!err){   
    mod.foo2(args,mycb2); //but have it act like a closure to mycb1 
    } 
    else{cb(err);} 
}; 

mod.A=function(){ 
    ... 
    mod.foo1(args,mycb1); //but have it act like a closure to A 
} 

mod.foo1 = function(args,cb){ 
    //do some work 
    cb(err); 
} 

mod.foo2 = function(args,cb){ 
    //do some work 
    cb(err); 
} 

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

+1

आप रन-टाइम पर ज्ञात कॉलबैक में ज्ञात मानों को सीमेंट करने के लिए Function.bind() का उपयोग कर सकते हैं। यह "निष्पादन के बिंदु से बंद होने" के करीब है, जैसा कि यह आपको सही ढंग से समझता है। – dandavis

+0

आप अत्यधिक भीड़ मॉड्यूल बंद होने के बिना राज्य को जारी रखने के लिए वादे का उपयोग कर सकते हैं – dandavis

+0

उत्कृष्ट सलाह। धन्यवाद। – rss181919

उत्तर

6

सामान्य रूप से, इन-लाइन में बंद करने के लिए कोई समस्या नहीं है जिसके पास बंद होने तक पहुंच है। आप एक सरल अज्ञात फ़ंक्शन के द्वारा फ़ंक्शन इन-लाइन बना सकते हैं जो शेष कॉल स्वीकार करते समय पैरामीटर के रूप में माता-पिता कॉलबैक में कुछ तर्क पास करता है (यानी आंशिक फ़ंक्शन), या आंशिक फ़ंक्शन स्वयं बनाने के लिए Function.bind() का उपयोग करके।

उदाहरण के लिए

, अगर आप शुरू में था:

function(...) { 
    // closure vars x1, y1 
    foo.bar(function(result) { 
     // do something with x1 and y1 
    }); 
} 

आप निकाल सकते है कि करने के लिए:

var callback = function(x1, y1, result) { 
    // do something with x1 and y1 
}; 

function(...) { 
    // closure vars x1, y1 

    // option 1: make your own partial function 
    foo.bar(function(result) { return callback(x1, y1, result); }); 
    // with ES6: foo.bar((result) => callback(x1, y1, result); }); 

    // option 2: use Function.bind 
    foo.bar(callback.bind(this, x1, y1);); 
} 
+0

यही मुझे चाहिए। उत्तर देने के लिए धन्यवाद। यह वास्तव में एक नौसिखिया मदद करता है :) – rss181919

1

यहाँ कोई बंद करने और कोई घोंसले के साथ एक नेस्टेड कॉलबैक उदाहरण है। यह निर्दिष्ट पृष्ठ को पकड़ता है, तीसरा लिंक पाता है, फिर उपयोगकर्ता को उस लिंक का स्रोत दिखाता है।

इस मामले में, जब कंसोल में यहां से चलाया जाता है और होम पेज खिलाया जाता है, तो लॉगआउट पृष्ठ तीसरा लिंक होता है, और इसकी सामग्री को सतर्क किया जाता है।

सभी कॉलबैक भाई बहन हैं, और कोई बाहर राज्य चर, सिर्फ शुद्ध कार्यात्मक async हैं:

// look ma, no nesting! 
function ajax(a, c) { 
    var e = new XMLHttpRequest; 
    e.onload= ajaxOnload.bind(this, c, e); 
    e.open("GET", a, !0); 
    e.send(); 
    return e 
} 

function ajaxOnload(c, e) { 
    c(e.responseText, e); 
} 

function cbFind3(cb, s){ 
    var t=document.createElement("body"); 
    t.innerHTML=s; 
    var lnk= t.getElementsByTagName("a")[3].href; 
    ajax(lnk, cb);  
} 

function grabThirdLinkSource(url, cb){ 
    ajax(url, cbFind3.bind(this, cb)); 
} 

grabThirdLinkSource("/", alert); 

यह सबसे अधिक उपयोगी नहीं उदाहरण है, लेकिन यह दिखाता है कि कैसे बाँध के साथ आमंत्रण भर में श्रृंखला कार्य (करने के लिए)। मैंने वेनिला अजाक्स का इस्तेमाल किया और यह दिखाने के लिए केवल वादे से बचा कि कैसे इस शैली की शैली बिना किसी जटिलताओं के प्रदर्शन करती है। यहां तक ​​कि AJAX सहायक भी घटना या पूरे xhr ऑब्जेक्ट के बजाय "कोर" कॉलबैक पर प्रतिक्रिया टेक्स्ट को फ़ीड करने के लिए एक गैर-नेस्टेड फ़ंक्शन का उपयोग करता है।

+0

धन्यवाद। आपका उदाहरण यह पुष्टि करने में सहायता करता है कि पिछले 2 उपयोगकर्ताओं ने क्या सुझाव दिया था। सच्चाई यह है कि मैं उसी वैरिएबल स्कोप के साथ निष्पादित करने के लिए कॉलबैक को मजबूर करना चाहता था कि कॉलिंग कोड निष्पादित हो रहा था और आप इसे जावास्क्रिप्ट में नहीं कर सकते। आप ऑब्जेक्ट स्कोप को मजबूर करने के लिए आंशिक फ़ंक्शंस या बाध्यकारी का उपयोग कर सकते हैं लेकिन चरणीय पहुंच केवल फ़ंक्शन पैरामीटर को पास करने के तर्कों के माध्यम से हासिल की जा सकती है। – rss181919

+0

आप _eval_ या _with_ के माध्यम से फ़ंक्शंस कहने के लिए लेक्सिकल स्कोप के साथ गड़बड़ कर सकते हैं, लेकिन तर्क पारित करने का कार्यात्मक दृष्टिकोण आम तौर पर लंबे समय तक बेहतर प्रदर्शन करता है और कम से कम आंशिक encapsulation, पुन: प्रयोज्यता, और अंतर्निहित "स्मृति प्रबंधन लागू करके प्रदर्शन के लिए बेहतर काम करता है "। यह पहली बार थोड़ा अलग लगता है, और यह है, लेकिन यह निरंतरता शैली आश्रित/संबंधित async प्रक्रियाओं के लिए वास्तव में अच्छी तरह से काम करती है। – dandavis

संबंधित मुद्दे