Asynkron och enkeltrådad JavaScript?
JavaScript är ett enkeltrådat språk och samtidigt också icke-blockerande, asynkront och samtidigt. Den här artikeln kommer att förklara för dig hur det händer.
Kolla in den tredje delen av vår Power of functional programming i JavaScript-artikelserien. Den här gången förklarar vår JavaScript-expert mer om Functor och Monad Maybe.
Ofta är det svårt att behålla oföränderligheten. Mönstret med att förpacka data i en behållare kommer till undsättning. Det säkrar värdena så att hanteringen av dem är säker med uteslutande av biverkningar.
Om du är ny här, se till att kolla mina sista 2 delar om funktionell programmering på The Codest blogg om:
Den har ingen komplex logik. Dess huvuduppgift är att förpacka kontexten och utföra de funktioner som den får utifrån på dem. Varje gång värdet ändras paketeras en ny containerinstans om och returneras. När du anropar karta som kräver en viss åtgärd, returnerar den en ny containerinstans med det värde som returneras av den skickade funktionen, samtidigt som principen om att den inte kan modifieras bibehålls.
const Functor = värde => ({
map: fn => Functor(fn(värde)),
chain: fn => fn(värde),
of: () => värde
});
karta - användbar när du vill ändra statusen för ett värde i en container men inte vill returnera det ännu.
kedja - används om du vill skicka ett värde till en funktion utan att ändra behållarens tillstånd. Vanligtvis i slutet av karta samtal.
av - returnera aktuellt värde
const randomInt = (max) => Math.floor(Math.random() * (max + 1))
const randomNumber = randomInt(200) // returnerar ett tal mellan 0 och 200
decrease(randomNumber) // returnerar (tal mellan 0 och 200) - 1
const randomIntWrapper = (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 = slumpmässigtIntWrapper(200)
randomNumber.of() // returnerar tal mellan 0 och 200
randomNumber.chain(decrease) // returnerar (tal mellan 0 och 200) - 1
Ibland behöver du, förutom de funktioner som utlöser det nya tillståndet för värdet, ytterligare logik dold i behållaren. Det är här monad kommer till nytta, eftersom det är en förlängning av funktor. Den kan t.ex. bestämma vad som ska hända när värdet har ett visst värde eller vilken väg nästa åtgärd ska ta.
Monad maybe löser problemet med värden som returnerar något som inte är sant. När detta händer kommer efterföljande karta ignoreras, men du kan returnera ett alternativ genom att anropa hämtaOr metod. Det gör att du kan undvika att använda if / else-operatorer, som är populära i tvingande programmering. Denna monad består av tre behållare:
Ingenting - körs när ett värde som inte är sant faller in i behållaren eller filter metoden returnerar falskt. Den används för att simulera utförandet av en funktion. Detta innebär att denna container tar emot funktionen men inte utför den.
Bara - är detta huvudbehållaren som utför alla funktioner, men om värdet ändras till ett falskt värde eller filter metoden returnerar false, kommer den att skicka den till Ingenting container.
Kanske - Jag tar startvärdet och bestämmer vilken container som ska anropas i början.
const Just = värde => ({
map: fn => Maybe(fn(värde)),
chain: fn => fn(värde),
av: () => value,
getOr: () => värde,
filter: fn => fn(värde) ? Just(värde) : Ingenting(),
typ: 'bara'
});
const Nothing = () => ({
map: fn => Ingenting(),
chain: fn => fn(),
av: () => Nothing(),
getOr: substitute => substitute,
filter: () => Ingenting(),
typ: 'ingenting'
});
const Maybe = värde =>
value === null || value === undefined || value.type === 'nothing'
? Ingenting()
: Just(värde)
Låt oss nu bygga upp det tidigare exemplet om villkoret. Om max är större än noll kommer funktionen att utföras. Annars kommer den att returnera 0.
const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} annat {
returnera 0
}
}
const bookMiddlePage = 200
const randomPage = randomInt(10) || bookMiddlePage // returnerar slumpmässigt
const randomPage = randomInt(-10) || bookMiddlePage // returnerar 200
const randomIntWrapper = (max) => Kanske
Kanske(max)
.filter(max => max > 0) // värdet false ignorerar ytterligare anrop
.map(öka)
.map(multiplyBy(Math.random())))
.map(matte.golv)
const bookMiddlePage = 200
// Bara en behållare
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // returnerar slumpmässigt
// Behållare för ingenting
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // returnerar 200