वैकल्पिक कॉलबैक के लिए जावास्क्रिप्ट शैली


93

मेरे कुछ कार्य हैं जो कभी-कभार (हमेशा नहीं) कॉलबैक प्राप्त करते हैं और इसे चलाते हैं। यह जाँच रहा है कि क्या कॉलबैक परिभाषित है / एक अच्छी शैली का कार्य करता है या क्या कोई बेहतर तरीका है?

उदाहरण:

function save (callback){
   .....do stuff......
   if(typeof callback !== 'undefined'){
     callback();
   };
};

आधुनिक ब्राउज़रों में आप सिर्फ इस्तेमाल कर सकते हैं typeof callback !== undefinedतो बाहर छोड़'
Snickbrack

1
और अगर आप बस फोन करते हैं save()? क्या कोई त्रुटि या लाइनिंग चेतावनी नहीं देगा क्योंकि एक तर्क गायब है? या यह पूरी तरह से ठीक है और कॉलबैक बस है undefined?
जोहो पिमेंटेल फेरेरा

जवाबों:


139

मैं व्यक्तिगत रूप से पसंद करता हूं

typeof callback === 'function' && callback();

typeofआदेश कुशल तथापि है और केवल के लिए इस्तेमाल किया जाना चाहिए "undefined"और"function"

इसके साथ समस्या यह typeof !== undefinedहै कि उपयोगकर्ता एक मूल्य में पास हो सकता है जो परिभाषित है और फ़ंक्शन नहीं है


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

1
@TJCrowder डोडी गलत शब्द हो सकता है, यह "object"95% समय पर मुक्केबाजी और वापसी के कारण अच्छी तरह से परिभाषित है लेकिन बेकार है ।
रेयानोस

1
typeofमुक्केबाजी का कारण नहीं है। typeof "foo"है "string", नहीं "object"। यह वास्तव में एकमात्र वास्तविक तरीका है जो आप बता सकते हैं कि क्या आप एक स्ट्रिंग आदिम या Stringवस्तु के साथ काम कर रहे हैं । (शायद आप सोच रहे हैं Object.prototype.toString, जो बहुत काम का है , लेकिन मुक्केबाजी का कारण बनता है।)
टीजे क्राउडर

4
अद्भुत तरीके से मुहावरेदार उपयोग &&
टीजे क्राउडर

@TJCrowder आपके पास एक बिंदु है, मुझे नहीं पता कि मूल्य स्ट्रिंग प्राइमेटरीज और बॉक्सिंग स्ट्रिंग ऑब्जेक्ट्स की तुलना करने का क्या है। इसके अलावा मैं सहमत हूं .toStringकि खोजने के लिए सुंदर है [[Class]]
Raynos

50

आप भी कर सकते हैं:

var noop = function(){}; // do nothing.

function save (callback){
   callback = callback || noop;
   .....do stuff......
};

यदि आप callbackकुछ स्थानों पर उपयोग करते हैं, तो यह विशेष रूप से उपयोगी है ।

इसके अतिरिक्त यदि आप उपयोग कर रहे हैं jQuery, तो आपके पास पहले से ही एक फ़ंक्शन है, इसे $ .noop कहा जाता है


4
मेरे विचार में, यह सबसे सुरुचिपूर्ण समाधान है।
निकोलस ले थिएरी डी'नेनेक्विन

2
माना। यह परीक्षण करना भी आसान बनाता है, क्योंकि अगर कोई शर्त नहीं है।

5
लेकिन यह पता नहीं है कि यह किस प्रकार का मुद्दा है? क्या होगा यदि मैं एक सरणी पास करूँ? या एक स्ट्रिंग?
झेरो

1
सरल करेंcallback = callback || function(){};
NorCalKnockOut

1
आप घोषणा में इसे डिफ़ॉल्ट मान देकर एक तर्क को वैकल्पिक भी बना सकते हैं:function save (callback=noop) { ...
कीथ

39

बस करो

if (callback) callback();

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



3

कॉलबैक को वैकल्पिक बनाने के बजाय, बस एक डिफ़ॉल्ट असाइन करें और इसे कॉल करें चाहे कोई भी हो

const identity = x =>
  x

const save (..., callback = identity) {
  // ...
  return callback (...)
}

इस्तेमाल के बाद

save (...)              // callback has no effect
save (..., console.log) // console.log is used as callback

ऐसी शैली को निरंतरता-गुजर शैली कहा जाता है । यहां एक वास्तविक उदाहरण है, combinationsजो एक ऐरे इनपुट के सभी संभावित संयोजनों को उत्पन्न करता है

const identity = x =>
  x

const None =
  Symbol ()

const combinations = ([ x = None, ...rest ], callback = identity) =>
  x === None
    ? callback ([[]])
    : combinations
        ( rest
        , combs =>
            callback (combs .concat (combs .map (c => [ x, ...c ])))
        )

console.log (combinations (['A', 'B', 'C']))
// [ []
// , [ 'C' ]
// , [ 'B' ]
// , [ 'B', 'C' ]
// , [ 'A' ]
// , [ 'A', 'C' ]
// , [ 'A', 'B' ]
// , [ 'A', 'B', 'C' ]
// ]

क्योंकि combinationsनिरंतरता-गुजर शैली में परिभाषित किया गया है, उपरोक्त कॉल प्रभावी रूप से समान है

combinations (['A', 'B', 'C'], console.log)
// [ []
// , [ 'C' ]
// , [ 'B' ]
// , [ 'B', 'C' ]
// , [ 'A' ]
// , [ 'A', 'C' ]
// , [ 'A', 'B' ]
// , [ 'A', 'B', 'C' ]
// ]

हम एक कस्टम निरंतरता भी पारित कर सकते हैं जो परिणाम के साथ कुछ और करता है

console.log (combinations (['A', 'B', 'C'], combs => combs.length))
// 8
// (8 total combinations)

निरंतर-गुजर शैली का उपयोग आश्चर्यजनक रूप से सुरुचिपूर्ण परिणामों के साथ किया जा सकता है

const first = (x, y) =>
  x

const fibonacci = (n, callback = first) =>
  n === 0
    ? callback (0, 1)
    : fibonacci
        ( n - 1
        , (a, b) => callback (b, a + b)
        )
        
console.log (fibonacci (10)) // 55
// 55 is the 10th fibonacci number
// (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...)


1

मैं इतना थक गया कि एक ही स्निपेट को देखते हुए और मैंने इसे लिखा:

  var cb = function(g) {
    if (g) {
      var args = Array.prototype.slice.call(arguments); 
      args.shift(); 
      g.apply(null, args); 
    }
  };

मुझे सौ तरह के काम करने हैं

  cb(callback, { error : null }, [0, 3, 5], true);

जो कुछ भी...

मुझे पूरा संदेह है कि "यह सुनिश्चित करें कि यह फ़ंक्शन है" रणनीति। केवल वैध मान एक फ़ंक्शन या मिथ्या हैं। यदि कोई गैर-शून्य संख्या या गैर-रिक्त स्ट्रिंग में गुजरता है, तो आप क्या करने जा रहे हैं? समस्या को अनदेखा करना इसे कैसे हल करता है?


फ़ंक्शन को पहले तर्क के रूप में कुछ मान स्वीकार करने के लिए ओवरलोड किया जा सकता है, पहला तर्क या दोनों मापदंडों के रूप में फ़ंक्शन। जाँच करने के लिए एक उपयोग-मामला है कि क्या यह एक फ़ंक्शन है। एक गलत कार्य को अंजाम देने के लिए गलत पैरामीटर को नजरअंदाज करना भी बेहतर है
रेयानोस

@Raynos - यह एक बहुत, बहुत विशिष्ट उपयोग मामला है। जावास्क्रिप्ट, कमजोर रूप से टाइप किया जा रहा है, जो भेद करने वाले प्रकारों में अच्छा नहीं है, और आमतौर पर नामित मापदंडों में अंतर करने से बेहतर है कि प्रकारों को अलग करने और यह अनुमान लगाने की कोशिश करें कि कॉलर क्या चाहता है:save( { callback : confirmProfileSaved, priority: "low" })
माल्वोलियो

मैं असहमत हूं, पर्याप्त प्रकार की जांच करने की क्षमता है। मैं विधि अधिभार पसंद करता हूं, लेकिन यह व्यक्तिगत प्राथमिकता है। इस तरह की चीज jQuery बहुत कुछ करता है।
रेयानोस

@ रेयानोस - गलत पैरामीटर को नजरअंदाज करना और फिर किसी फंक्शन को अंजाम देने के लिए एरर को फेंकना ज्यादा बुरा है। एक विशिष्ट मामले पर विचार करें: लाइब्रेरी फ़ंक्शन कुछ अतुल्यकालिक गतिविधि कर रहा है और कॉलिंग फ़ंक्शन को अधिसूचित करने की आवश्यकता है। तो एक अनौपचारिक उपयोगकर्ता, अनदेखा करना और विफल होना एक समान लगता है: गतिविधि कभी पूरी नहीं होती है। हालांकि, एक परिष्कृत उपयोगकर्ता (उदाहरण के लिए, मूल प्रोग्रामर), एक विफलता एक त्रुटि संदेश और एक स्टैक ट्रेस देता है जो सीधे समस्या पर इंगित करता है; पैरामीटर को नजरअंदाज करने का अर्थ है कि "कुछ भी नहीं" होने का कारण निर्धारित करने के लिए थकाऊ विश्लेषण।
मालवोलियो

हालांकि एक व्यापार बंद है। त्रुटि को फेंकना रन-टाइम को क्रैश कर देगा, लेकिन इसे अनदेखा करने से इसके आसपास के अन्य कोड सामान्य हो जाएंगे।
रेयानोस

1

एक मान्य फ़ंक्शन फ़ंक्शन प्रोटोटाइप पर आधारित है, उपयोग:

if (callback instanceof Function)

यह सुनिश्चित करने के लिए कि कॉलबैक एक फ़ंक्शन है


0

यदि कॉलबैक चलाने का मानदंड यह है कि इसकी परिभाषा है या नहीं, तो आप ठीक हैं। इसके अलावा, मैं यह जांचने का सुझाव देता हूं कि क्या वास्तव में इसके अलावा कोई कार्य है।


0

मैंने कॉफी-स्क्रिप्ट की ओर रुख किया है और पाया कि डिफ़ॉल्ट तर्क इस समस्या को हल करने का एक अच्छा तरीका है

doSomething = (arg1, arg2, callback = ()->)->
    callback()

0

यह आसानी से ArgueJS के साथ किया जा सकता है :

function save (){
  arguments = __({callback: [Function]})
.....do stuff......
  if(arguments.callback){
    callback();
  };
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.