Fonctions paresseuses JavaScript

Salut


J'ai pensé ici pour vous expliquer comment en JavaScript en utilisant la bibliothèque Fluture vous pouvez créer et utiliser des fonctions paresseuses. Ce sera un bref aperçu sur la façon de créer des fonctions, comment gérer les erreurs et un peu sur la concurrence. Cerveau de programmation fonctionnelle Je ne vais pas planer! Je te le promets!


Fluture


Fluture est une bibliothèque développée par le développeur Aldwin Vlasblom qui implémente Future. Future est une alternative à Promise, qui possède une API beaucoup plus puissante qui permet la mise en œuvre de l'annulation, une "récursivité" sûre, une exécution "sans erreur" (en utilisant l'un ou l'autre) et un petit chariot de fonctionnalités intéressantes.


Je pense que cela vaut la peine de vous parler des méthodes (monades) que j'utiliserai dans les exemples ci-dessous.


  • .of(Any) - crée un avenir à partir de la valeur transmise
  • .map(Function) - non, ce n'est pas Array.map , c'est une fonction de transformation similaire à Promise.then
  • .chainRej(Function) - comme Promise.catch une erreur
  • .fork(Function, Function) - démarre l'exécution future

Création d'une fonction paresseuse


Pour ma part, j'ai mis en évidence deux approches principales pour créer des fonctions paresseuses dans Fluture. La première approche consiste à créer une fonction qui accepte les données source et renvoie un Future prêt à être exécuté. La deuxième approche consiste à créer un avenir avec toutes les transformations décrites, puis à lui transmettre les données.


Pas clair Prenons un exemple! Nous avons une telle fonction


 const multiply10 = x => x * 10; 

Maintenant, faites-la paresseuse en utilisant la première approche


 const multiply10 = x => x * 10; const lazyMultiply10 = (x) => Future .of(x) //  Future   .map(multiply10); //     lazyMultiply10(2).fork(console.error, console.log); // -> 20 

Trop encombrant, non? Essayons d'écrire de manière plus concise en utilisant la deuxième approche.


 const multiply10 = x => x * 10; const lazyMultiply10 = Future.map(multiply10); const value = Future.of(2); //     Future lazyMultiply10(value).fork(console.error, console.log); // -> 20 

Déjà mieux, mais toujours encombrant. Il doit être plus compact!


 const lazyMultiply10 = Future.map(x => x * 10); lazyMultiply10(Future.of(2)).fork(console.error, console.log); // -> 20 

En fait, ces approches ne s'excluent pas mutuellement et peuvent être utilisées ensemble.


 const lazyMultiply10 = Future.map(x => x * 10); const someCalculation = a => Future .of(a) .map(v => v + 1) .chain(v => lazyMultiply10(Future.of(v)); someCalculation(10).fork(console.error, console.log); // -> 110 

Gestion des erreurs


La gestion des erreurs dans Future n'est pratiquement pas différente de la gestion des erreurs dans Promise. Allons souviens toi imaginez une fonction qui fait une requête à une API tierce, peu stable.


 const requestToUnstableAPI = query => request({ method: 'get', uri: `http://unstable-site.com/?${query}` }) .then(res => res.data.value) .catch(errorHandler); 

Même fonction, mais enveloppé dans Future


 const lazyRequestToUnstableAPI = query => Future .tryP(() => request({ method: 'get', uri: `http://unstable-site.com/?${query}` })) .map(v => v.data.value) .chainRej(err => Future.of(errorHandler(err)); 

En fait, la gestion des erreurs peut être rendue plus flexible. Pour ce faire, nous avons besoin de la structure Either, et cette petitesse dépasse la portée de mon examen.


Accès simultané


Pour travailler avec le parallélisme, Future implémente deux méthodes race(Futures[]) (similaire à Promise.race ), parallel(n, Futures[]) et les both(Future, Future) , mais c'est un cas particulier de parallel .


La méthode parallel prend deux arguments, le nombre de Future parallèle et le tableau avec Future. Pour rendre le comportement parallel identique à la méthode Promise.all , vous devez définir le nombre d' Promise.all à définir comme Infinity .


Ici aussi, nous ne pouvons pas nous passer d'exemples.


 const requestF = o => Future.tryP(() => request(o)); const parallel1 = Future.parallel(1); const lazyReqs = parallel1( [ 'http://site.com', 'http://another-site.com', 'http://one-more-site.com', ] .map(requestF) ); lazyReqs.fork(console.error, console.log); // -> [Result1, Result2, Result3] 

Compatible promesse


Il n'y a pas de place pour Promise dans JavaScript, et il est peu probable que quelqu'un soit satisfait si votre méthode retourne un futur obscur. Pour ce faire, Future a une méthode .promise() , qui démarrera l'exécution de Future et l'enveloppera dans Promise.


 Future .of(10) .promise(); // -> Promise{value=10} 

Les références



C'est peut-être tout ce que je voulais vous dire. Si le sujet est intéressant, faites-le moi savoir, je vous en dirai plus sur la gestion des erreurs. Et oui, ne me gronde pas beaucoup, c'est mon premier post sur Habré.

Source: https://habr.com/ru/post/fr435838/


All Articles