Mis à jour le 11/11/2024
// in C#
La programmation parallèle a pour objectif de faire tourner du code sur plusieurs processeurs (ou plusieurs cœurs). Ceci permettant de réaliser des opérations en parallèle et donc dans certains cas optimiser le temps pour de lourds traitements.
Processeurs
L'objectif est donc de diviser un problème en plusieurs parties et faire s'exécuter des bouts de solutions de manière parallèle afin d'optimiser le temps de traitement.
A noter que c'est utilisable dans certains contexte mais que dans d'autres, ça peut être s'ajouter de la complexité pour peu de gains.
Quand utiliser la Programmation Parallèle ?
Il y a plusieurs cas d'usages récurrents pour la PP :
Task-bases Asynchronous Pattern (TAP)
Event-bases Asynchronous Pattern (EAP)
Asynchronous Programming Model (APM)
On utilise une seule méthode pour compléter une suite de tâche asynchrone. C'est le type recommandé en .Net et nous nous attarderons sur ce type.
On utilise des events pour produire des comportements asynchrone. C'est en quelques sortes l'ancienne méthode donc nous l'aborderons pas.
Mise en place de méthodes avec Begin & End et une interface IAsyncResult pour traiter des opérations asynchrones. C'est une façon de faire qui n'est plus recommandé du tout aujourd'hui.
.Net 1.1
.Net 2.0
.Net 4.5
Process | Threads |
---|---|
Opérations lourdes | Opérations plus légères |
A son propre espace mémoire | Partage la mémoire du process auquel ils appartiennent |
Communication inter-process lente et adresse mémoire différentes | D'où la communication plus rapide entre threads |
Passer d'un process à l'autre est coûteux | Passer d'un thread à l'autre est moins coûteux |
Aucun partage de mémoire | Partage de la mémoire |
Un process est une unité de code qui permet de réaliser des opérations (instructions). On peut voir les Threads comme des micro-process qui peuvent communiquer entre eux et utiliser une mémoire commune
Juste à titre informatif, voici comment fonctionnent les Threads
Ces termes doivent déjà vous parler mais il s'agit de programmation concurrentielle & de programmation parallèle.
Concurrentielle
Parallèle
CPU
Unité de travail
CPU 1 / Thread
Unité de travail
CPU 2 / Thread
Unité de travail
Parallèle
Unité de travail
Unité de travail
Asynchrone
=
Parallèle + interdépendances
Quelques informations sur un programme qui utilise les process : Google Chrome.
Comme on peut le voir dans le Task Manager, Chrome utilise plusieurs processus, d'ailleurs il en met en place parfois plusieurs pour chaque onglet. Ceci apportant plusieurs avantages :
Voici un exemple que j'utiliserai afin de vous montrer comment faire de la programmation parallèle (Exemple de Microsoft)
Concurrentielle
Asynchrone
Bien que ça ne soit pas vraiment au programme de ce cours, je sais que ça en intéressera plus d'un (une) d'approfondir la théorie de la PP.
Quelques termes pour guider vos recherches
Des gens intéressés pour faire une petite présentation de la théorie ?
Nous allons voir plusieurs classes disponibles dans le Framework .Net afin de réaliser de la programmation parallèle en C# de nos jours (TAP) :
Premièrement, le mot clé async permet de définir une méthode comme étant asynchrone.
Ensuite, le mot clé await permet de définir que l'on attend le retour d'une méthode asynchrone
On peut avoir une méthode async en void, mais ceci nous forcerait à ne pas pouvoir attendre le retour, donc nous ne serions pas sûr de la fin de l'exécution de la méthode.
Si on déclare une méthode comme asynchrone, il doit y avoir un await dedans
Nous utilisons
également les méthodes asynchrones d'appels d'API ici
Ces mots clés sont toujours utilisé en programmation parallèle, ils permettent de définir une méthode comme asychrone (async) et d'attendre le retour (await)
S'il on déclare une méthode comme asynchrone, il doit y avoir un await dedans
Nous utilisons
également les méthodes asynchrones d'appels d'API ici
On utilise Task en type de retour car il n'est pas possible d'attendre sur void
La classe Task a pour but de vous permettre de gérer vos appels asynchrones en C#, c'est la plus utilisée.
Voici les différentes possibilités que l'on va explorer :
Class | Objectif |
---|---|
Task | Gérer une unité de travail |
Task<TResult> | Unité de travail avec une valeur de retour |
TaskFactory | Créer une Task |
TaskFactory<TResult> | Créer une Task & continuité de Task avec le même type de retour |
TaskCompletionSource | Pour gérer manuellement le workflow d'une Task |
Premier exemple simple d'utilisation d'une Task :
On déclare le type de retour en Task afin de pouvoir l'await.
On utilise Task.WhenAll()
pour attendre que toutes les opérations soient
terminées
Task.WhenAll respecte l'ordre de passage des tasks dans le retour de result[] (même si les temps d'exécution sont différents)
Voici les méthodes que nous allons utiliser pour réaliser des opérations parallèles
On fait en sorte que
le thread attende 2 secondes pour simuler une tâche lourde
Attention, il y a plusieurs moyens d'appeler une Task, nous en verrons cinq. Dont trois seulement sont optimisés, ne faites pas l'erreur, sinon l'asynchronisme ne sert à rien.
On déclare le type de retour
en Task<string> afin de pouvoir l'await avec retour
Chaque tâche est attendue l'une après l'autre
Ce moyen attend les tâches l'une après l'autre et prend donc 6 secondes
Attention, il y a plusieurs moyens d'appeler une Task, nous en verrons cinq. Dont deux seulement sont optimisés, ne faites pas l'erreur, sinon l'asynchronisme ne sert à rien.
SendEmailAsync n'ayant
pas de type de retour, on peut l'appeler ainsi également
Ce moyen attend les tâches l'une après l'autre, sauf SendEmailAync et prend donc 4 secondes
Seul cet appel sans type de
retour sera réalisé en même temps que les autres
Attention, il y a plusieurs moyens d'appeler une Task, nous en verrons cinq. Dont deux seulement sont optimisés, ne faites pas l'erreur, sinon l'asynchronisme ne sert à rien.
On créer une Task
pour chaque méthode à appeler
Ce moyen réalise les tâches en parallèle, ceci prend donc 2 secondes
Les appels sont fait de manière asynchrone
Attention, il y a plusieurs moyens d'appeler une Task, nous en verrons cinq. Dont deux seulement sont optimisés, ne faites pas l'erreur, sinon l'asynchronisme ne sert à rien.
On créer une Task
pour chaque méthode à appeler
Ce moyen réalise les tâches en parallèle, ceci prend donc 2 secondes
On utilise Task.WhenAll
pour attendre les actions en parallèle
Clean !
Attention, il y a plusieurs moyens d'appeler une Task, nous en verrons cinq. Dont deux seulement sont optimisés, ne faites pas l'erreur, sinon l'asynchronisme ne sert à rien.
On créer une Task
pour chaque méthode à appeler
On créer une List de Tasks
On boucle sur la liste de tasks
Ce moyen prend également 2 secondes mais permet d'avoir la main sur les Tasks
On boucle sur la liste de tasks
On boucle sur la liste de tasks
Dès qu'une tâche est terminée, on la supprime avec Remove
Afin que vous pratiquiez un peu l'utilisation de la classe Task, vous devez réutiliser les exemples précédents et réaliser différents appels asynchrones pour pratiquer.
Le but est de reprendre le code et le comprendre :
Posez des questions si des choses ne sont pas claires pour vous
Il est également possible d'utiliser une Factory pour créer une Task et la démarrer :
On peut également mettre
un appel à une méthode ici
Voici un exemple un peu plus complet qui permet de réaliser des opérations de manière parallèle ainsi que les ajouter à une somme totale et l'afficher.
Par contre impossible de faire des opérations asynchrones dans DoComputation
Il est également possible d'utiliser Run afin de réaliser des opérations similaires avec possibilité d'asynchronisme (recommandé)
Exemple avec Task.Run
Task permet également d'utiliser ContinueWith afin de pouvoir continuer un traitement asynchrone en s'assurant d'avoir l'ensemble des résultats attendus avant de continuer le code tout en gérant efficacement les exceptions.
Exemple ContinueWith
ContinueWith permet également de gérer les exceptions (il est d'ailleurs conseiller de gérer les différents statuts de retour). Voici un petit exemple
Exemple ContinueWith
Un petit exercice d'application du ContinueWith. Il vous est demandé de réalisé le code (via une Task<string>) permettant de gérer le retour de cette méthode async d'appel à une api quelconque.
Vous devez gérer les différents status (RanToCompletion & Faulted).
Pensez à tester avec une api qui n'existe pas (enlevez le i à official par exemple)
Posez des questions si des choses ne sont pas claires pour vous
static async Task<string> FetchDataAsync()
{
using (HttpClient httpClient = new HttpClient())
{
HttpResponseMessage response = await httpClient.GetAsync("https://official-joke-api.appspot.com/random_joke");
response.EnsureSuccessStatusCode(); // Permet de lever une exception si l'appel n'a pas renvoyé une réponse valable
return await response.Content.ReadAsStringAsync();
}
}
Le but de cet exercice est de travailler encore une fois la classe Task sur un exemple légèrement plus complexe et moins guidé.
Vous avez le code de la méthode "DoWork". Votre objectif est d'appeler trois fois cette méthode avec les paramètres suivants :
Bien entendu vous devez appelez les trois méthodes de manière asynchrone.
Pour terminer, vous devez afficher le cumul des 3 délais retournés PUIS ajouter 500 au cumul pour l'afficher.
static int DoWork(string taskName, int delayMilliseconds)
{
Console.WriteLine("{0} starting...", taskName);
Task.Delay(delayMilliseconds).Wait();
Console.WriteLine("{0} completed.", taskName);
return delayMilliseconds;
}
Comme on l'a vu, la classe Task a pour objectif de réaliser une opération de manière asynchrone, souvent des opérations lourdes. Une autre possibilité pour la PP est d'utiliser la classe Parallel. Cette dernier va vous permettre d'effectuer un nombre de fois des opérations en parallèle. L'objectif est de simplifier la réalisation d'actions en parallèle.
A noter qu'on utilise Parallel lorsqu'il n'y a pas d'interdépendances entre les éléments que l'on veut rendre asynchrone.
Attention, ce moyen de paralléliser les instructions ne permet pas de garder l'ordre de départ de la liste.
Il est possible de limiter le nombre de processeurs utilisés lors de l'utilisation de la classe Parallel. Ceci se fait avec des options de la classe ParallelOptions.
Il existe aussi des options pour mettre en place un token d'annulation (CancellationToken) & pour choisir le planificateur de tâche (TaskScheduler). On l'a entrevu normalement, mais c'est aussi possible avec Task (et des constructeurs différents)
A noter, ceci est très rarement utile, surtout qu'il se peut que d'une machine à l'autre ces éléments varient.
Un autre exemple de code et une autre façon de pouvoir utiliser la classe Parallel. Notez dans l'exemple du dessous que nous utilisons une aggrégation de résultat.
Attention, ce moyen de paralléliser les instructions ne permet pas de garder l'ordre de départ de la liste.
Un autre exemple de code et une autre façon de pouvoir utiliser la classe Parallel
Attention, ce moyen de paralléliser les instructions ne permet pas de garder l'ordre des lignes provenant d'un fichier
Un autre exemple de code et une autre façon de pouvoir utiliser la classe Parallel, mais cette fois-ci avec Parallel.Invoke et en modifiant le retour (Upper / Lower)
Attention, ce moyen de paralléliser les instructions ne permet pas de garder l'ordre des lignes provenant d'un fichier
Dans ce contexte, nous ne travaillons donc plus avec des Task, mais avec des Action.
Chaque action peut être effectuée en parallèle et être appelé de manière asynchrone grâce à la Parallel.Invoke.
Ce code mettra à peine plus de 1,5 secondes à s'exécuter car les actions sont déclenchées en parallèle.
Une partie de ces exercices sont aussi présents dans les slides, mais ils ont été légèrement adapté pour un peu plus vous forcer à réfléchir durant la pratique.
Posez des questions si des choses ne sont pas claires pour vous
Envoyer Exercice1_PP.md
+ file1.txt
+ file2.txt
Un dernier moyen existe afin de réaliser des opérations parallèles sur des listes d'éléments. Nous pouvons faire du PLinq pour réaliser du parallélisme avec Linq (mais c'est peu recommandé en règle général)
On utilise la méthode
AsParallel() sur une liste ou un tableau afin de rendre les itérations asynchrones
Ceci permet d'afficher les éléments de la liste de manière asynchrone, attention ici aussi ça ne garde pas l'ordre de départ de la liste
On peut utiliser la
méthode ForAll() sur le retour de AsParallel().Where()
Voici un exemple de code ou on utilise PLinq mais on force le fait de respecter l'ordre de la liste de départ avec AsOrdered() puis un nouveau ForEach() dessus.
On ajoute la méthode
AsOrdered() pour garder l'ordre des entrées, mais c'est pas tout
Ici, la liste de départ est respectée. A noter que si vous êtes en .Net Framework < 7, la durée d'exécution sera plus longue sur ce cas. Sinon elle sera plus rapide car il y a eu de grosses optimisations en Framework 7.0 sur le PLinq
On doit retransformer le retour de AsParallel().AsOrdered().
Puis, on transforme en liste, puis on fait un ForEach
Voici un autre exemple de code un peu plus complet pour l'utilisation de PLinq.
De nouveau, ici la l'ordre de la liste de départ n'est pas respecté.
Encore un autre exemple de code où ici on combine PLinq et l'utilisation de Task
De nouveau, ici la l'ordre de la liste de départ n'est pas respecté.
On utilise la méthode
ContinueWith() sur la liste
pour effectuer une opération
asynchrone
Nous sommes contraint
de réaliser un foreach classique afin de pouvoir se référer à task.Result
Une partie de ces exercices sont aussi présents dans les slides, mais ils ont été légèrement adapté pour un peu plus vous forcer à réfléchir durant la pratique.
Posez des questions si des choses ne sont pas claires pour vous
Envoyer Exercice2_PP_PLinq.md
Il est important de savoir que la première exception levée stoppera l'exécution de votre code si vous utilisez les Exceptions classiques dans votre code.
Ici, nous simulons les exception (tests) mais comme ça, seule la première exception est récupérée
Il est important de savoir que la première exception levée stoppera l'exécution de votre code si vous utilisez les Exceptions classiques dans votre code.
En créant votre propre classe d'exception, vous pouvez récupérer toutes les exceptions pour toutes les tâches
Honnêtement, je n'utilise pas trop cette classe, mais autant la voir rapidement pour en voir un exemple (sans faire d'exo)
Une partie ou l'on génère un résultat
Honnêtement, je n'utilise pas trop cette classe, mais autant la voir rapidement pour en voir un exemple (sans faire d'exo)
Une partie ou l'on génère une exception intentionnellement
Concrètement, je vais vous envoyer le code non asynchrone, vous allez devoir le rendre asynchrone, selon les captures ci-desous.
Conseil pratique : Vous pouvez utiliser des Tasks et utiliser WhenAny() pour bien implémenter tout ça
L'évaluation ressemblera assez à ce type de traitements parallèles, donc je vous enverrai le corrigé et prenez le temps de l'analyser / poser des questions
Il existe plusieurs avantages à mettre en place une API de manière asynchrone :
Il existe plusieurs façons de mettre en place une API en .Net, nous allons en utiliser une assez simple en utilisant FastEndpoint. (A ma connaissance, il faut avoir dans outils => obtenir les outils et fonctionnalités => Développement web et ASP.Net)
Petite démonstration rapide de comment mettre en place une API avec FastEndpoint + Parallélisation des appels
Documentation FastEndpoint (si besoin)
Nous allons réaliser les étapes ensemble pour un simple test, puis vous aurez un exercice à réaliser qui s'en rapproche afin de vraiment tester tout ça.
Etapes à suivre :
using FastEndpoints;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFastEndpoints();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseFastEndpoints();
app.Run();
Nous allons réaliser les étapes ensemble pour un simple test, puis vous aurez un exercice à réaliser qui s'en rapproche afin de vraiment tester tout ça.
Etapes à suivre :
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"Https": {
"Url": "https://localhost:5001"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Nous allons réaliser les étapes ensemble pour un simple test, puis vous aurez un exercice à réaliser qui s'en rapproche afin de vraiment tester tout ça.
Etapes à suivre :
public class EndpointTest : EndpointWithoutRequest
{
public override void Configure()
{
Get("api/test");
AllowAnonymous();
}
public override async Task HandleAsync(CancellationToken tc)
{
await Task.Delay(1000);
await SendAsync(new
{
test = "test"
}, cancellation: tc);
}
}
Nous allons réaliser les étapes ensemble pour un simple test, puis vous aurez un exercice à réaliser qui s'en rapproche afin de vraiment tester tout ça.
Etapes à suivre :
// code in Program.cs
HttpClient client = new HttpClient();
var testTask = ApiAsyncMethods.GetTest(client);
var testResult = await testTask;
Console.WriteLine("Test result value {0}", testResult);
Attention, j'ai fait
exprès ici de ne pas vous donner les lignes de code pour l'asynchrone
Nous allons réaliser les étapes ensemble pour un simple test, puis vous aurez un exercice à réaliser qui s'en rapproche afin de vraiment tester tout ça.
Etapes à suivre :
internal class TestFastEndpoint
{
public string test { get; set; }
}
public static async Task<string> GetTest(HttpClient client)
{
HttpResponseMessage response = await client.GetAsync("https://localhost:5001/api/test");
var jsonContent = await response.Content.ReadAsStringAsync();
var test = JsonSerializer.Deserialize<TestFastEndpoint>(jsonContent);
return test.test; // Oui, c'est pas très beau mais c'est un test !
}
Exercice
Nous allons parler d'asynchronisme et faire des exemples en Node.js, mais les principes sont similaires en js, node, typescript,...
Ce n'est pas vraiment le but de la formation d'être complet sur l'asynchronisme en JS, mais nous allons couvrir 3 topics principaux :
J'espère que cette introduction suffira à vous mettre le pied à l'étrier afin d'aller chercher plus d'info par vous même dans les exercices proposés...
Si vous êtes familier avec javascript, vous connaissez les callbacks, c'est un moyen de passer une fonction en paramètre d'une autre fonction pour qu'elles soient exécutées une fois qu'une opération asynchrone est terminée.
const fs = require('fs');
fs.readFile('file.txt', 'utf-8',
(err, data) => {
if (err) {
console.error("Error :", err);
return;
}
console.log("File content :", data);
}
);
Ce troisième paramètre, c'est mon callback
La syntaxe est pas folle de base...
On peut donc créer autant de callbacks qu'on veut et les enchaîner comme on le souhaite, voyons un exemple plus complet.
Montrer l'exemple CallBackHell
Dans cet exemple, on voit que ça peut vite devenir complexe de maîtriser la pyramide de Doom ou ce qui est nommé callback hell.
C'est pour cette raison que les Promises ont vu le jour et nous allons plutôt nous attarder là dessus !
Et encore... On n'a pas vu comment gérer les erreurs dans cet exemple... Et on ne va pas perdre le temps de le faire.
🤮
Les promises sont le meilleur moyen de mieux gérer ces problèmes d'asynchronisme et de callback hell de js.
Créer une Promise
Appeler une Promise (v1)
const promise = new Promise((resolve) => {
// Simulate an asynchronous operation
setTimeout(() => {
// Resolve the promise
resolve('Promise resolved')
}, 2000)
})
promise.then((result) => {
console.log(result)
})
On créer un objet de type Promise, on lui passe resolve en argument et on peut appeler resolve pour finaliser notre opération promise.
On appelle la promise et avec then((result) => {...}) on attend le résultat pour effectuer l'affichage
Ce qui se passe dans le then se passe après le retour de la promise
Ce qui est resolve est passé en paramètre dans le then
On a également la possibilité de gérer les cas d'échecs, avec reject et le catch.
Créer une Promise
Appeler une Promise (v1)
const rejectedPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const random = Math.round(Math.random())
if (random)
resolve('Promise resolved')
else
reject('Promise rejected')
}, 2000)
})
rejectedPromise.then((result) => {
console.log(result)
}).catch((error) => {
console.error(error)
})
Le random ne sert qu'à pouvoir tester les cas, l'idée est de gérer les cas de réussite avec resolve et les cas d'échecs avec reject.
Cette fois on peut ajouter le catch pour gérer le cas où on est passé dans le reject et qu'on a voulu gérer une erreur
Promise.Any() : Retourne la première promise qui a été résolue, ceci permettant de gérer certains workflow particuliers
Promise.Any()
import fetch from 'node-fetch'
const promisePokemonOne = fetch('https://pokeapi.co/api/v2/pokemon/ditto')
const promisePokemonTwo = fetch('https://pokeapi.co/api/v2/pokemon/pikachu')
const firstResult = Promise.any([promisePokemonOne, promisePokemonTwo])
firstResult
.then((response) => response.json())
.then((data) => {
console.log(`Pokemon type : ${data.types[0].type.name}`)
})
.catch((error) => {
console.error('Error fetching Pokemon data:', error)
})
Ici, le résultat dépendra de chaque exécution, il sera donc différent d'une exécution à l'autre
Attention ici, fetch retourne une promise et il nous faut le resultat json()
Promise.All() : Attend que toutes les promises passées soient résolues avant de pouvoir chaîner sur les résultats
Promise.All()
const promiseOne = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise one resolved')
}, 2000)
})
const promiseTwo = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise two resolved')
}, 1000)
})
// This will wait for all promises to be resolved
const allPromises = Promise.all([promiseOne, promiseTwo])
// We can then use the results of all promises that comes as an array
allPromises
.then((results) => {
console.log(`1 : ${results[0]}`)
console.log(`2 : ${results[1]}`)
})
On va donc pouvoir itérer sur chaque promise les unes après les autres lorsqu'elles seront TOUTES terminées de manière asynchrone.
Promise.All() : Attend que toutes les promises passées soient résolues avant de pouvoir chaîner sur les résultats
Promise.All()
import fetch from 'node-fetch'
const promisePokemonOne = fetch('https://pokeapi.co/api/v2/pokemon/ditto')
const promisePokemonTwo = fetch('https://pokeapi.co/api/v2/pokemon/pikachu')
const allResults = Promise.all([promisePokemonOne, promisePokemonTwo])
allResults
.then((responses) => Promise.all(responses.map((response) => response.json())))
.then((data) => {
console.log(`Pokemon types : ${data[0].types[0].type.name} and ${data[1].types[0].type.name}`)
})
.catch((error) => {
console.error('Error fetching Pokemon data:', error)
})
Juste un exemple supplémentaire utilisant l'API pokemon, notez la particularité concernant le .map utilisé sur le responses...
Un exemple "concret" de mise en place de Promise et de les chaîner tout en ayant la possibilité de faire autre chose en même temps
Voir PromisesPizza (code)
Pizza
Laundry
Order (2s)
Bake (2s)
Receive (2s)
Eat(2s)
DoLaundry (7s)
Total time
8 secondes
Async & await sont des mots clés importants dans l'asynchronisme en javascript. Ils seront bien souvent préférés à l'utilisation de then / catch pour des plusieurs raisons que l'on listera dans la slide suivante.
Async / await
function getRandomNumber() {
return new Promise((resolve) => {
setTimeout(() => {
const random = Math.floor(Math.random() * 10) + 1
resolve(random)
}, 2000)
})
}
async function main() {
try {
const randomNumber = await getRandomNumber()
console.log(`Random number is ${randomNumber}`)
} catch (error) {
console.error(`Error: ${error}`)
}
}
main()
Dans un contexte de fichier index.js on ne peut pas directement utiliser async / await, c'est pourquoi on créer une méthode "main", on la met en async et on peut utiliser await dedans.
+ Des try / catchs classiques. Et c'est tout !
Quelques remarques sur async / await. Et donc pourquoi choisir plutôt ce moyen en amont des then / catch.
Permet une syntaxe plus propre, du code plus clean |
Async / await doivent toujours être utilisés ensemble |
Async / await ne concerne que le receveur d'infos |
On peut await n'importe quelle promise ! |
Une méthode async simple retourne une promise en JS |
N'importe quelle méthode peut être mise async |
Améliore et clarifie la gestion d'erreurs avec les try / catch |
Voici exactement le même exemple que précédemment, mais cette fois, c'est fait en utilisant les mots clés async / await
Voir PromisesPizzaAsync (code)
Pizza
Laundry
Order (2s)
Bake (2s)
Receive (2s)
Eat(2s)
DoLaundry (7s)
Total time
8 secondes
Premier graphe simple
Il faut donc que
Un simple console log de la lettre suffit.
Voici trois exercices que vous pouvez réaliser pour pratiquer les Promises en le faisant proprement avec l'appels en async / wait.
Vous avez trois graphes à implémenter (voir les 3 slides d'exercices)
Voici trois exercices que vous pouvez réaliser pour pratiquer les Promises en le faisant proprement avec l'appels en async / wait.
Vous avez trois graphes à implémenter (voir les 3 slides d'exercices)
Second graphe un peu plus complexe
Il faut donc que
Un simple console log de la lettre suffit.
Voici trois exercices que vous pouvez réaliser pour pratiquer les Promises en le faisant proprement avec l'appels en async / wait.
Vous avez trois graphes à implémenter (voir les 3 slides d'exercices)
Troisième graphe un peu plus casse tête...
Il faut donc que
Un simple console log de la lettre suffit.
Vous pourrez vous exercer et aller plus loin via ce lien github. Les principes qui y sont présentés sont plus avancés que ce qui a été vu dans le lien précédent. (C'est du typescript ici, mais c'est le lien le plus intéressant et complet que j'ai pu trouver)
Ce lien est vraiment très complet et les exercices sont incroyables pour aller plus loin dans les notions de programmation parallèle avec js. Je vous conseille vivement de faire le maximum d'exercices.
BON COURAGE !
Evaluation
Réaliser un workflow asynchrone.
Envoyer le fichier Evaluation_PP.md
+ Eval_file1.txt
+ Eval_file2.txt
Calcul somme des nombres de 1 -> 3000
Traiter 2 fichiers calculer le nombre de mots
Traiter 2 fichiers calculer le nombre de "Lorem"
Afficher le résultat de la somme totale des 5 résultats
Affichage console
Affichage console
Affichage console
N'oubliez pas d'afficher le temps de tout ce traitement et le résultat final !
Utilisez Enumerable.Range(1, 3000)
BON COURAGE !
Evaluation rattrapage
Réaliser un workflow asynchrone. (Seul le traitement des fichiers s'effectue de manière asynchrone)
Envoyer le fichier Evaluation_PP_rattrapage.md
+ Eval_file1_rattrapage.txt
+ Eval_file2_rattrapage.txt
Calcul somme des nombres de 1 -> 10000
Traiter 2 fichiers calculer le nombre de mots
Traiter 2 fichiers calculer le nombre de "Lorem"
Afficher le résultat de la somme totale des 6 résultats
Affichage console
Affichage console
Affichage console
N'oubliez pas d'afficher le temps de tout ce traitement et le résultat final !
Faire un appel à l'API et compter le nombre de mot du retour