BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Actualités core.async : une autre approche de la programmation asynchrone avec Clojure et ClojureScript

core.async : une autre approche de la programmation asynchrone avec Clojure et ClojureScript

Bien que cela fasse moins d'un mois depuis l'annonce de la sortie de core.async, la librairie pour Clojure/ClojureScript a déjà fait l'objet d'un bon nombre de billets de blogs décrivant comment l'utiliser efficacement pour éviter l'enfer des callbacks et présentant quelques lignes de code simples résultant en d'impressionnantes démos dans le navigateur. core.async est une librairie écrite en Clojure à utiliser autant avec Clojure qu'avec ClojureScript. Clojure est une implémentation de Lisp pour la JVM. ClojureScript est une deuxième implémentation d'un large sous-ensemble de Clojure compilant vers du JavaScript. core.async est une bonne illustration du pouvoir que propose Lisp en matière de macros. Alors qu'avec la plupart des langages, les choses faites par core.async nécessiteraient des modifications du langage, avec Lisp il est possible de les implémenter en utilisant des macros.

Comme le nom le suggère, core.async est conçu pour rendre la programmation asynchrone plus simple. Il emprunte beaucoup d'idées à Go, plus spécifiquement les notions de goroutines (appelés go blocks dans core.async) et de channels. Un channel est une file avec un ou plusieurs producteurs, ou publishers, et un ou plusieurs consommateurs, consumers. Le mécanisme est simple : les producteurs placent les données dans la file, les consommateurs les y récupèrent. La donnée étant immuable dans Clojure/ClojureScript, les channels fournissent un moyen sûr de communiquer entre threads. Ce point n'est cependant pas particulièrement intéressant dans le contexte de ClojureScript, JavaScript étant à thread unique.

core.async offre deux façons d'écrire et de lire dans les channels : de façon bloquante et de façon non-bloquante. Une écriture bloquante bloque le thread tant que le channel a de l'espace pour l'écriture (la taille du buffer d'un channel est configurable), une lecture bloquante bloque un thread jusqu'à ce qu'une valeur devienne disponible pour lecture. Des opérations plus intéressantes, et les seules supportées par ClojureScript, sont les lectures et écritures asynchrones, seulement autorisées dans les "go blocks". Les go blocks sont écrits dans un style synchrone et sont convertis en interne en machine à état qui les exécute de façon asynchrone.

Observez le code suivant, basé sur core.async :

    (let [ch (chan)]
      (go (while true
            (let [v (<! ch)]
              (println "Read: " v))))
      (go (>! ch "hi")
          (<! (timeout 5000))
          (>! ch "there")))

Dans cet exemple, une nouvelle variable locale est introduite, ch, qui est un nouveau channel. Dans la portée du let, deux go blocks sont définis. Le premier est une boucle infinie qui lit (<!) un nouvelle valeur depuis le channel ch dans la variable v et affiche en sortie standard "Read" suivi de la valeur lue. Le second go block écrit (>!) deux valeurs dans le channel ch : "hi" puis, après une attente de 5 secondes, "there". L'attente de 5 secondes est implémentée en effectuant une opération de lecture dans un channel de timeout, qui est un channel se refermant tout seul (il retourne nil) après un laps de temps défini. Lorsque ce code est exécuté dans la REPL de Clojure (par exemple), il retourne instantanément. Il affiche ensuite "Read : hi" et, 5 secondes après, "Read: there".

Tout développeur JavaScript sera choqué par cette boucle while : vous ne pouvez pas créer de boucle bloquante comme celle-là : le navigateur va se figer pendant 5 secondes. La "magie" de core.async tient dans le fait qu'en interne, le corps de chaque go block est converti en machine à état et que les lectures dans le channel, d'apparence synchrone, sont transformées en appels asynchrones.

Voici quelques ressources pour en savoir plus sur core.async et comment cette librairie peut changer le développement web :

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT