Asynchrone et monotâche JavaScript ?
JavaScript est un langage monotâche et, en même temps, non bloquant, asynchrone et concurrent. Cet article vous expliquera comment cela se passe.
Voici la troisième partie de notre série d'articles sur la puissance de la programmation fonctionnelle dans JavaScript. Cette fois-ci, notre expert JavaScript vous en dit plus sur Functor et Monad Maybe.
Souvent, il est difficile de maintenir les données non modifiables. Le modèle d'enveloppement des données dans un conteneur vient à la rescousse. Il sécurise les valeurs de sorte que leur manipulation est sûre et exclut les effets secondaires.
Si vous êtes nouveau ici, assurez-vous de consulter mes deux dernières parties concernant la programmation fonctionnelle sur le blog The Codest :
Il n'a pas de logique complexe. Sa tâche principale consiste à envelopper le contexte et à exécuter les fonctions qu'il reçoit de l'extérieur. Chaque fois que la valeur change, une nouvelle instance de conteneur est reconditionnée et renvoyée. Lors de l'appel à la fonction carte qui prend une action spécifique, il renvoie une nouvelle instance de conteneur avec la valeur renvoyée par la fonction passée, tout en maintenant le principe de non-modification.
const Functor = value => ({
map : fn => Functor(fn(valeur)),
chain : fn => fn(valeur),
of : () => valeur
}) ;
carte - utile lorsque vous souhaitez modifier l'état d'une valeur dans un conteneur mais que vous ne souhaitez pas encore la renvoyer.
chaîne - utilisé pour passer une valeur à une fonction sans modifier l'état du conteneur. Habituellement à la fin de carte appels.
de - renvoie la valeur actuelle
const randomInt = (max) => Math.floor(Math.random() * (max + 1))
const randomNumber = randomInt(200) // renvoie un nombre entre 0 et 200
decrease(randomNumber) // renvoie (nombre entre 0 et 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 = randomIntWrapper(200)
randomNumber.of() // renvoie un nombre entre 0 et 200
randomNumber.chain(decrease) // renvoie (nombre entre 0 et 200) - 1
Parfois, en plus des fonctions qui déclenchent le nouvel état de la valeur, vous avez besoin d'une logique supplémentaire cachée dans le conteneur. C'est là que la monade s'avère utile, puisqu'il s'agit d'une extension de foncteur. Il peut, par exemple, décider de ce qui doit se passer lorsque la valeur a une certaine valeur ou de la voie à suivre pour les actions suivantes.
La monade maybe résout le problème des valeurs qui renvoient des valeurs fausses. Lorsque cela se produit, les carte sont ignorés, mais il vous permet de renvoyer une alternative en appelant la fonction getOr . Elle permet d'éviter l'utilisation d'opérateurs Elle vous permet d'éviter l'utilisation des opérateurs if / else, qui sont très répandus en impératif programmation. Cette monade se compose de trois conteneurs :
Rien - s'exécute lorsqu'une valeur qui n'est pas vraie tombe dans le conteneur ou dans l'espace de stockage. filtre renvoie un faux. Elle est utilisée pour simuler l'exécution d'une fonction. Cela signifie que ce conteneur reçoit la fonction mais ne l'exécute pas.
Juste - il s'agit du conteneur principal qui exécute toutes les fonctions, mais si la valeur devient fausse ou si le conteneur filtre renvoie une valeur fausse, il la transmettra à la méthode Rien contenant.
Peut-être - Je prends la valeur initiale et décide quel conteneur appeler au début.
const Just = valeur => ({
map : fn => Maybe(fn(valeur)),
chain : fn => fn(valeur),
of : () => valeur,
getOr : () => valeur,
filter : fn => fn(valeur) ? Just(valeur) : Nothing(),
type : 'just'
}) ;
const Nothing = () => ({
map : fn => Nothing(),
chain : fn => fn(),
of : () => Nothing(),
getOr : substitute => substitute,
filter : () => Nothing(),
type : 'nothing'
}) ;
const Maybe = value =>
value === null || value === undefined || value.type === 'nothing'
? Nothing()
: Just(valeur)
Reprenons maintenant l'exemple précédent en ce qui concerne la condition. Si max est supérieur à zéro, la fonction sera exécutée. Dans le cas contraire, elle renverra 0.
const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} else {
retour 0
}
}
const bookMiddlePage = 200
const randomPage = randomInt(10) || bookMiddlePage // retourne aléatoire
const randomPage = randomInt(-10) || bookMiddlePage // renvoie 200
const randomIntWrapper = (max) =>
Maybe(max)
.filter(max => max > 0) // la valeur false ignore les autres appels
.map(augmentation)
.map(multiplyBy(Math.random()))
.map(Math.floor)
const bookMiddlePage = 200
// Juste un conteneur
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // retourne aléatoire
// Conteneur sans rien
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // renvoie 200