Asynkron og enkelttrådet JavaScript?
JavaScript er et enkelttrådet språk og samtidig også ikke-blokkerende, asynkront og samtidig. Denne artikkelen forklarer hvordan det skjer.
Sjekk den tredje delen av vår artikkelserie Power of functional programming in JavaScript. Denne gangen forklarer vår JavaScript-ekspert mer om Functor og Monad Maybe.
Ofte er det vanskelig å vedlikeholde det som ikke kan endres. Mønsteret med å pakke inn data i en container kommer til unnsetning. Det sikrer verdiene slik at det er trygt å håndtere dem uten at det oppstår bivirkninger.
Hvis du er ny her, må du huske å sjekke de to siste delene mine om funksjonell programmering på The Codest-bloggen om:
Den har ingen kompleks logikk. Hovedoppgaven er å pakke inn konteksten og utføre funksjonene den mottar fra utsiden på dem. Hver gang verdien endres, pakkes en ny containerinstans inn på nytt og returneres. Når du kaller kart som krever en bestemt handling, returnerer den en ny containerforekomst med verdien som returneres av den overførte funksjonen, samtidig som prinsippet om ikke-modifiserbarhet opprettholdes.
const Functor = value => ({
map: fn => Functor(fn(verdi)),
chain: fn => fn(verdi),
of: () => value
});
kart - nyttig når du vil endre tilstanden til en verdi i en container, men ikke ønsker å returnere den ennå.
kjede - brukes hvis du vil sende en verdi til en funksjon uten å endre beholderens tilstand. Vanligvis på slutten av kart samtaler.
av - returnere gjeldende verdi
const randomInt = (max) => Math.floor(Math.random() * (max + 1))
const randomNumber = randomInt(200) // returnerer et tall mellom 0 og 200
decrease(randomNumber) // returnerer (tall mellom 0 og 200) - 1
const randomIntWrapper = (max) => (max)
Functor(max)
.map(increase) // max + 1
.map(multiplyBy(Math.random()))) // Math.random() * (max + 1)
.map(Math.floor) // Math.floor(Math.random() * (max + 1))
const randomNumber = randomIntWrapper(200)
randomNumber.of() // returnerer tall mellom 0 og 200
randomNumber.chain(decrease) // returnerer (tall mellom 0 og 200) - 1
I tillegg til funksjonene som utløser den nye tilstanden til verdien, trenger du noen ganger ytterligere logikk skjult i beholderen. Det er her monad kommer til nytte, ettersom det er en utvidelse av funktor. Den kan for eksempel bestemme hva som skal skje når verdien har en viss verdi, eller hvilken vei de neste handlingene skal ta.
Monaden løser kanskje problemet med verdier som ikke returnerer true. Når dette skjer, vil påfølgende kart anrop ignoreres, men du kan returnere et alternativ ved å kalle getOr metoden. Det gjør at du unngår bruk av if/ else-operatorer, som er populære i tvingende nødvendig programmering. Denne monaden består av tre beholdere:
Ingenting - kjøres når en verdi som ikke er sann, faller inn i beholderen eller filter metoden returnerer false. Den brukes til å simulere utførelsen av en funksjon. Det betyr at denne containeren mottar funksjonen, men ikke utfører den.
Bare - er dette hovedbeholderen som utfører alle funksjonene, men hvis verdien endres til en falsk verdi eller filter metoden returnerer false, vil den sende den videre til Ingenting container.
Kanskje - Jeg tar startverdien og bestemmer hvilken container som skal kalles i starten.
const Just = verdi => ({
map: fn => Maybe(fn(verdi)),
chain: fn => fn(verdi),
of: () => value,
getOr: () => value,
filter: fn => fn(verdi) ? Just(verdi) : Nothing(),
type: 'just'
});
const Nothing = () => ({
map: fn => Nothing(),
chain: fn => fn(),
of: () => Nothing(),
getOr: substitute => substitute,
filter: () => Nothing(),
type: 'ingenting'
});
const Maybe = verdi =>
value === null || value === undefined || value.type === 'nothing'
? Nothing()
: Just(verdi)
La oss nå bygge det forrige eksempelet om betingelsen. Hvis max er større enn null, vil funksjonen bli utført. Ellers vil den returnere 0.
const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} ellers {
return 0
}
}
const bookMiddlePage = 200
const randomPage = randomInt(10) || bookMiddlePage // returnerer tilfeldig
const randomPage = randomInt(-10) || bookMiddlePage // returnerer 200
const randomIntWrapper = (max) => (max)
Maybe(max)
.filter(max => max > 0) // verdien false ignorerer videre anrop
.map(økning)
.map(multiplyBy(Math.random())))
.map(Math.floor)
const bookMiddlePage = 200
// Bare beholder
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // returnerer tilfeldig
// Ingenting beholder
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // returnerer 200