Pisałem kod, który robi coś, co wygląda:
function getStuffDone(param) { | function getStuffDone(param) {
var d = Q.defer(); /* or $q.defer */ | return new Promise(function(resolve, reject) {
// or = new $.Deferred() etc. | // using a promise constructor
myPromiseFn(param+1) | myPromiseFn(param+1)
.then(function(val) { /* or .done */ | .then(function(val) {
d.resolve(val); | resolve(val);
}).catch(function(err) { /* .fail */ | }).catch(function(err) {
d.reject(err); | reject(err);
}); | });
return d.promise; /* or promise() */ | });
} | }
Ktoś mi powiedział, że nazywa się to odpowiednio „ odroczonym antipatternem ” lub „ Promise
konstruktorem antipatternem ”, co jest złego w tym kodzie i dlaczego nazywa się to antyatternem ?
javascript
promise
q
bluebird
es6-promise
Benjamin Gruenbaum
źródło
źródło
getStuffDone
opakowanie funkcji i po prostu używa literału Promise?catch
blok wgetStuffDone
opakowaniu antipattern?Promise
przykładu natywnego masz również niepotrzebne opakowania funkcji dla programów obsługi.then
i.catch
obsługi (tzn. Może to być po prostu.then(resolve).catch(reject)
.) Idealna burza anty-wzorów.Odpowiedzi:
Odroczone antywzorzec projektowy (obecnie wyraźne-budowa antywzorzec projektowy) wymyślone przez Esailija jest wspólne antywzorzec projektowy ludzi, którzy są nowicjuszami w obietnice zrobić, zrobiłem to sam, kiedy po raz pierwszy użyty obietnic. Problem z powyższym kodem polega na tym, że nie wykorzystuje się tego, co obiecuje łańcuch.
Obietnice mogą wiązać się z łańcuchem
.then
i możesz bezpośrednio zwrócić obietnice. Twój kodgetStuffDone
może zostać przepisany jako:Obietnice polegają na zwiększeniu czytelności kodu asynchronicznego i zachowaniu się jak kod synchroniczny bez ukrywania tego faktu. Obietnice reprezentują abstrakcję nad wartością jednorazowej operacji, abstrakcyjnie pojmują wyrażenie lub wyrażenie w języku programowania.
Powinieneś używać odroczonych obiektów tylko wtedy, gdy konwertujesz API na obietnice i nie możesz tego robić automatycznie, lub gdy piszesz funkcje agregacji, które łatwiej wyrazić w ten sposób.
Cytując Esailija:
źródło
.defer()
interfejs API do nowszego (i rzucił bezpiecznie) konstruktora obietnic, nie przestał (w żaden sposób) odrzucać pojęcia konstruowania obietnic :)Co jest z tym nie tak?
Szczęściarz. Niestety prawdopodobnie tak nie jest, ponieważ prawdopodobnie zapomniałeś o jakiejś sprawie krawędziowej. W ponad połowie przypadków, które widziałem, autor zapomniał zająć się obsługą błędów:
Jeśli druga obietnica zostanie odrzucona, stanie się to niezauważona, a nie zostanie propagowana do nowej obietnicy (gdzie zostanie zrealizowana) - a nowa obietnica pozostanie na zawsze w oczekiwaniu, co może spowodować wycieki.
To samo dzieje się w przypadku, gdy kod wywołania zwrotnego powoduje błąd - np. Gdy
result
nie maproperty
znaku i zostanie zgłoszony wyjątek. To pozostanie nierozstrzygnięte i pozostawi nową obietnicę nierozstrzygniętą.W przeciwieństwie do tego, użycie
.then()
automatycznie zajmuje się tymi dwoma scenariuszami i odrzuca nową obietnicę, gdy wystąpi błąd:Odroczony antypattern jest nie tylko uciążliwy, ale również podatny na błędy . Korzystanie
.then()
z łańcuchów jest znacznie bezpieczniejsze.Naprawdę? Dobrze. Będzie to jednak dość szczegółowe i obfite, zwłaszcza jeśli korzystasz z biblioteki obietnic, która obsługuje inne funkcje, takie jak anulowanie lub przekazywanie wiadomości. A może tak będzie w przyszłości, a może chcesz zamienić swoją bibliotekę na lepszą? W tym celu nie będziesz chciał przepisać kodu.
Metody bibliotek (
then
) nie tylko natywnie obsługują wszystkie funkcje, ale mogą także mieć pewne optymalizacje. Korzystanie z nich prawdopodobnie przyspieszy kod lub przynajmniej pozwoli na optymalizację w przyszłych wersjach biblioteki.Jak tego uniknąć?
Tak więc za każdym razem, gdy znajdziesz ręczne tworzenie
Promise
lubDeferred
już istnieją obietnice, najpierw sprawdź interfejs API biblioteki . Odroczony antypattern jest często stosowany przez ludzi, którzy widzą obietnice [tylko] jako wzorzec obserwatora - ale obietnice są czymś więcej niż tylko wywołaniami zwrotnymi : powinny być możliwe do skomponowania. Każda przyzwoita biblioteka ma wiele łatwych w użyciu funkcji do komponowania obietnic w każdy możliwy do pomyślenia sposób, dbając o wszystkie rzeczy niskiego poziomu, z którymi nie chcesz sobie poradzić.Jeśli zauważyłeś potrzebę złożenia obietnic w nowy sposób, który nie jest obsługiwany przez istniejącą funkcję pomocnika, pisanie własnej funkcji z nieuniknionymi Odroczeniami powinno być ostatnią opcją. Rozważ przejście na bardziej funkcjonalną bibliotekę i / lub zgłoś błąd w bieżącej bibliotece. Jego opiekun powinien być w stanie wyodrębnić kompozycję z istniejących funkcji, zaimplementować dla ciebie nową funkcję pomocniczą i / lub pomóc w identyfikacji przypadków skrajnych, które należy obsłużyć.
źródło
setTimeout
, w których można zastosować konstruktor, ale nie można go uznać za „Promise constructor anitpattern”?setTimeout
”, ale „ sama funkcjasetTimeout
”.setTimeout
”, ale„setTimeout
sama funkcja ”„ Czy można opisać, powiązać z różnicami między nimi?setTimeout
wyraźnie różni się od samej funkcjisetTimeout
, prawda?