Asynchroon en single-threaded JavaScript?
JavaScript is een single-threaded taal en tegelijkertijd ook non-blocking, asynchroon en concurrent. Dit artikel legt je uit hoe dat in zijn werk gaat.
Bekijk het derde deel van onze Power of functional programming in JavaScript artikelenserie. Deze keer legt onze JavaScript expert meer uit over Functor en Monad Maybe.
Onwijzigbaar houden is vaak moeilijk te onderhouden. Het patroon om gegevens in een container te verpakken biedt redding. Het beveiligt de waarden zodat er veilig mee kan worden omgegaan en neveneffecten worden uitgesloten.
Als je hier nieuw bent, bekijk dan zeker mijn laatste 2 delen over functioneel programmeren op The Codest blog over:
Het heeft geen complexe logica. De belangrijkste taak is om de context in te pakken en de functies die het van buitenaf ontvangt erop uit te voeren. Telkens wanneer de waarde verandert, wordt een nieuwe containerinstantie opnieuw ingepakt en teruggestuurd. Wanneer de kaart methode, die een specifieke actie uitvoert, retourneert het een nieuwe containerinstantie met de waarde die is geretourneerd door de doorgegeven functie, terwijl het principe van niet-wijzigbaarheid behouden blijft.
const Functor = value => ({
map: fn => Functor(fn(value)),
keten: fn => fn(waarde),
van: () => value
});
kaart - handig als je de status van een waarde in een container wilt wijzigen, maar deze nog niet wilt retourneren.
ketting - wordt gebruikt als je een waarde wilt doorgeven aan een functie zonder de toestand van de container te wijzigen. Meestal aan het einde van kaart oproepen.
van - huidige waarde retourneren
const randomInt = (max) => Math.floor(Math.random() * (max + 1))
const randomNumber = randomInt(200) // geeft getal tussen 0 en 200 terug
decrease(randomNumber) // geeft (getal tussen 0 en 200) - 1 terug
const randomIntWrapper = (max) =>
Functor(max)
.map(verhogen) // 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() // geeft getal tussen 0 en 200 terug
randomNumber.chain(decrease) // geeft (getal tussen 0 en 200) - 1 terug
Soms heb je, naast de functies die de nieuwe toestand van de waarde triggeren, extra logica nodig die verborgen zit in de container. Dit is waar monad van pas komt, omdat het een uitbreiding is van functor. Het kan bijvoorbeeld beslissen wat er moet gebeuren als de waarde een bepaalde waarde heeft of welk pad de volgende acties moeten volgen.
Monad lost misschien het probleem op van waarden die niet waar retourneren. Wanneer dit gebeurt, kunnen volgende kaart aanroepen worden genegeerd, maar je kunt wel een alternatief retourneren door de getOr methode. Hiermee kun je het gebruik van if / else operatoren vermijden, die populair zijn in dwingend programmeren. Deze monade bestaat uit drie containers:
Niets - wordt uitgevoerd wanneer een waarde die niet waar is in de container valt of filter Methode retourneert false. Deze wordt gebruikt om de uitvoering van een functie te simuleren. Dit betekent dat deze container de functie ontvangt, maar deze niet uitvoert.
Gewoon - dit is de hoofdcontainer die alle functies uitvoert, maar als de waarde verandert in een valse waarde of filter methode false retourneert, wordt deze doorgegeven aan de Niets container.
Misschien - Ik neem de beginwaarde en beslis welke container aan het begin wordt aangeroepen.
const Just = waarde => ({
map: fn => Maybe(fn(value)),
keten: fn => fn(waarde),
van: () => value,
getOr: () => waarde,
filter: fn => fn(waarde) ? Gewoon(waarde) : Niets(),
type: 'gewoon'.
});
const Nothing = () => ({
map: fn => Niets(),
keten: fn => fn(),
van: () => Nothing(),
getOr: vervanger => vervanger,
filter: () => Niets(),
type: 'niets
});
const Maybe = waarde =>
value === null || value === undefined || value.type === 'nothing'
? Niets()
: Gewoon()
Laten we nu het vorige voorbeeld over de voorwaarde bouwen. Als max groter is dan nul, wordt de functie uitgevoerd. Anders wordt 0 geretourneerd.
const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} else {
return 0
}
}
const bookMiddlePage = 200
const randomPage = randomInt(10) || bookMiddlePage // geeft random terug
const randomPage = randomInt(-10) || bookMiddlePage // geeft 200 terug
const randomIntWrapper = (max) =>
Misschien(max)
.filter(max => max > 0) // waarde false negeert verdere oproepen
.map(verhogen)
.map(multiplyBy(Math.random())
.map(Math.floor)
const bookMiddlePage = 200
// Gewoon container
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // geeft random terug
// Niets container
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // geeft 200 terug