Pytanie Styl JavaScript: opcjonalne wywołania zwrotne


Mam pewne funkcje, które będę chciał czasami uruchomić wywołanie zwrotne, ale nie zawsze, sprawdza, czy wywołanie zwrotne jest zdefiniowane / funkcja dobry styl lub czy istnieje lepszy sposób?

przykład:

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

76
2017-07-22 15:56


pochodzenie


w nowoczesnych przeglądarkach możesz po prostu użyć typeof callback !== undefined więc pomiń ' - Snickbrack
i jeśli po prostu zadzwonisz save()? Czy to nie spowoduje błędu lub ostrzeżenia lingingowego, ponieważ brakuje argumentu? Lub jest w porządku, a callback jest po prostu undefined ? - João Pimentel Ferreira


Odpowiedzi:


Ja osobiście wolę

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

The typeof komenda jest jednak podejrzana i powinna być używana tylko dla "undefined" i "function"

Problemy z typeof !== undefined jest to, że użytkownik może przekazać zdefiniowaną wartość i nie jest funkcją


113
2017-07-22 15:58



typeof nie jest podejrzany. Czasami jest niejasny, ale nie nazwałbym go podejrzanym. Uzgodniono jednak, że jeśli zamierzasz wywoływać wywołanie zwrotne jako funkcję, najlepiej sprawdzić, czy jest to funkcja, a nie numer. :-) - T.J. Crowder
@ T.J.Crowder dodgy może być złym słowem, jest dobrze zdefiniowany, ale bezużyteczny ze względu na boks i powrót "object" 95% czasu. - Raynos
typeof nie powoduje boksowania. typeof "foo" jest "string", nie "object". W rzeczywistości jest to jedyny prawdziwy sposób, w jaki można stwierdzić, czy mamy do czynienia z prymitywem ciągu lub String obiekt. (Być może myślisz o tym Object.prototype.toString, który jest bardzo przydatny, ale powoduje boks.) - T.J. Crowder
Cudownie idiomatyczne użycie && tak poza tym. - T.J. Crowder
@ T.J.Crowder Masz punkt, nie wiem, jaka jest wartość porównywania prymitywów ciągów i pudełkowych obiektów String. Zgadzam się również .toStringjest cudowny w znalezieniu [[Class]]. - Raynos


Możesz także:

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

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

Jest to szczególnie przydatne, jeśli zdarzy ci się użyć callback w kilku miejscach.

Dodatkowo, jeśli używasz jQuerymasz już taką funkcję, to się nazywa $ .noop


41
2017-07-22 15:59



Moim zdaniem jest to najbardziej eleganckie rozwiązanie. - Nicolas Le Thierry d'Ennequin
Zgoda. To również ułatwia testowanie, ponieważ nie ma żadnego warunku jeśli.
To jest bardziej eleganckie niż najlepsza głosowana sugestia imho. - mefiX
ale to nie rozwiązuje problemu typu, prawda? co jeśli przekażę tablicę? lub ciąg? - Zerho
Uprość do callback = callback || function(){}; - NorCalKnockOut


Po prostu rób

if (callback) callback();

Wolę wywoływać wywołanie zwrotne, jeśli zostało dostarczone, bez względu na to, jaki to jest. Nie pozwól mu działać bezgłośnie, więc implementor wie, że przekazał niepoprawną argumentację i może ją naprawić.


27
2018-03-31 11:16



Podoba mi się to rozwiązanie, proste i działa dobrze. - Domenico Monaco


Dodając do tego, co powiedział Pablo, na najnowszym ECMAScript, jest to poprawne:

// @param callback Default value is a noop fn.
const wow = (callback = ()=>{}) => {
   callback();
};

Należy pamiętać, że użytkownik może przekazać coś innego niż funkcję i ją zepsuje.


2
2017-12-20 13:20





Jeśli kryterium uruchomienia wywołania zwrotnego jest takie, czy jest zdefiniowane, czy nie, wtedy wszystko jest w porządku. Sugeruję również sprawdzenie, czy jest to rzeczywiście funkcja dodatkowa.


0
2017-07-22 15:59





Byłem tak zmęczony widząc ten sam fragment w kółko, napisałem to:

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

Mam setki funkcji, które robią takie rzeczy

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

lub cokolwiek...

Jestem sceptycznie nastawiony do całej strategii "upewnij się, że to funkcja". Jedyne uzasadnione wartości to funkcja lub falsy. Jeśli ktoś przechodzi pod niezerową liczbą lub niepustym łańcuchem, co zamierzasz zrobić? Jak ignorowanie problemu rozwiązuje go?


0
2017-07-22 16:24



Funkcja może być przeciążona, aby przyjąć jakąś wartość jako pierwszy argument, funkcję jako pierwszy argument lub oba parametry. Istnieje przypadek użycia do sprawdzenia, czy jest to funkcja. Lepiej jest też zignorować niewłaściwy parametr, a następnie wygenerować błąd dla wykonania funkcji - Raynos
@Raynos - To bardzo, bardzo konkretny przypadek użycia. JavaScript, będąc słabo napisanym typem, nie jest dobry w rozróżnianiu typów i zazwyczaj lepiej jest przekazywać nazwane parametry niż próbować odróżnić typy i odgadnąć, czego chce wywoływać: save( { callback : confirmProfileSaved, priority: "low" }) - Malvolio
Nie zgadzam się, istnieje wystarczająca zdolność sprawdzania typu. Wolę przeciążanie metod, ale to osobiste preferencje. Jest to coś, co jQuery robi bardzo. - Raynos
@Raynos - Jest gorzej zignorować niewłaściwy parametr, a następnie wygenerować błąd dla wykonania funkcji. Rozważmy typowy przypadek: funkcja biblioteczna wykonuje pewne asynchroniczne działanie, a funkcja wywołująca musi zostać powiadomiona. Tak więc niewyszukany użytkownik, ignorowanie i niepowodzenie wydaje się taki sam: działanie wydaje się nigdy nie być zakończone. Jednak dla wyrafinowanego użytkownika (na przykład oryginalnego programisty), awaria daje komunikat o błędzie i ślad stosu, który wskazuje bezpośrednio na problem; zignorowanie parametru oznacza uciążliwą analizę w celu ustalenia, co spowodowało "nic". - Malvolio
trzeba jednak wymyślić kompromis. Rzucanie błędu spowoduje zawieszenie się czasu wykonywania, ale zignorowanie go spowoduje, że inny kod wokół niego wykona się normalnie. - Raynos


Grzeszyłem się przy kawie i znalazłem domyślne argumenty, które są dobrym sposobem na rozwiązanie tego problemu

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

0
2018-03-14 13:19





Można to łatwo zrobić ArgueJS:

function save (){
  arguments = __({callback: [Function]})
.....do stuff......
  if(arguments.callback){
    callback();
  };
};

0
2018-04-12 16:41





Ważna funkcja jest oparta na prototypie Function, użyj:

if (callback instanceof Function)

aby upewnić się, że wywołanie zwrotne jest funkcją


0
2017-12-26 18:36