Jakiś sensowny sposób obsługiwania wyjątków?

0

Wyjątki bywają IMO użyteczne, ale mają swoje wady, największym chyba jest brak wygodnego mechanizmu obsługi ich. Zaczerpnięta jeszcze z C++ konstrukcja try/catch w wielu wypadkach bywa tak (...) niewygodna, że ja nie widzę, jak można zapisać to w miarę zwięźle i czytelnie.

Przykład. value inputa o typie number ma być sparsowane jako Decimal i przepchnięte do kontrolerów wyżej zgodnie z Reactową maksymą Lifting State Up. Może być tak, że użytkownik nie poda liczby do inputa i jest to poprawna sytuacja, tyle że wtedy parsowanie jako Decimal rzuca. Nie wiem, czy jest możliwe, by przeglądarka wysłała event change w sytuacji, gdy użytkownik wpisał bzdury, ale na wszelki wypadek w takiej sytuacji także chcę przepchnąć w górę null, no bo z perspektywy logiki trudno to traktować inaczej, jak brak wartości.

Cały kod:

onChange(e) {
	let ret;
	try {
		ret = new Decimal(e.target.value);
	} catch(err) {
		if (err instanceof Error && /DecimalError/.test(err.message)) {
			this.props.onChange(null);
			return;
		} else {
			throw err;
		}
	}
	this.props.onChangeMaks(ret);
}

(sprawdzanie, czy błąd jest rzucony przez Decimal także na podstawie ichniej dokumentacji.

Dla porównania parseInt zwraca NaN przy błędzie parsowania. Gdybym więc mógł użyć parseInt to obsługa byłaby prosta:

onChange(e) {
    const ret = parseInt(e.target.value);
    this.props.onChange(!isNaN(ret) ? ret : null);
}

Czy jest jakiś sposób, by przepisać ten kod obsługujący wyjątek parsowania w sensowniejszy sposób?

2

Też nie lubię try + catch.
Owrapuj to sobie w funkcję. Ogólnie lubię brzydkie rzeczy wrapowaćw funkcje. Wtedy są one zamknięte w jednym miejscu i nie drażnią oczu i duszy.

const toDecimal = (val) => {
    try {
        return new Decimal(e.target.value);
    } catch(err) {
        if (err instanceof Error && /DecimalError/.test(err.message)) {
            return null;
        } else {
            throw err;
        }
    }
};

// niżej

onChange(e) {
    this.props.onChange(toDecimal(e.target.value)); // w Twoim przykładzie na dole było onChangeMaks - zapewne pominąłeś uproszczenie tutaj, w drugim było zwykłe onChange i tutaj to zastosowałem
}

a swoją drogą to mnie razi:
/DecimalError/.test(err.message);
Zaprzęganie RegExpów do takiej głupoty.

err.message.includes("DecimalError") to w zasadzie to samo, a z racji testowania instanceof Error nie powinno tu być zaskoczeń i pojawienia się znikąd innego typu niż string w err.message. PS: Wieczny hejt na JS za możliwość rzucania czegoś co nie jest instancją Error. Ale mam na to wrapper ;)

0

Dzięki za radę.

Użyłeś tutaj const toDecimal = (val) => { zamiast function toDecimal(val) { - ma to jakieś poważne uzasadnienie, czy to tylko styl?

Inna sprawa, że powoli się zastanawiam, czy parsowanie tego w onChange jest w ogóle prawidłowe - przecież tę samą wartość React za chwilę wsadzi z powrotem do value inputa. Na oko działa prawidłowo, ale powstaje pytanie, czy nie będzie jakiś nieprawidłowych edge case'ów z kropkami itp?

0

ma to jakieś poważne uzasadnienie, czy to tylko styl?

poważnego uzasadnienia nie ma, ale te zapisy nie są jednoznaczne. Różnica jest w tym na co wskazuje this w ciele funkcji oraz mój zapis (tzw. arrow function) nie podlega hoistingowi ( nie mam dobrego arta pod ręką, więc pierwszy lepszy: https://developer.mozilla.org/pl/docs/Glossary/Hoisting )

Inna sprawa, że powoli się zastanawiam, czy parsowanie tego w onChange jest w ogóle prawidłowe - przecież tę samą wartość React za chwilę wsadzi z powrotem do value inputa. Na oko działa prawidłowo, ale powstaje pytanie, czy nie będzie jakiś nieprawidłowych edge case'ów z kropkami itp?

Ciężko mi odpowiedzieć na pytanie, nie znam tej libki. Nie wiem jak "ciężkie" jest utworzenie instancji. Jeżeli nie wykryłeś problemów i naprawdę spróbowałeś wielu rzeczy, żeby to zepsuć i się nie udało - to chyba jest ok. Ja zazwyczaj wszelkie parsowanie pozostawiam sobie na koniec - na evencie blur, ale to mocno zależy od przypadku. Zawsze można połączyć oba rozwiązania i np. zrobić sobie debouncing eventu onChange i parsować go tylko przy zatrzymaniu pisania na pół sekundy i wtedy reagować na ew. błędy.

0

Jesli chodzi o czytelnosc ja ostatnimi czasami lubie to robic golang style
https://www.npmjs.com/package/await-to-js
https://dev.to/bibekkakati/error-handling-in-javascript-golang-style-4fj1

1 użytkowników online, w tym zalogowanych: 0, gości: 1