Here is a nice intro form Krasimir https://krasimirtsonev.com/blog/article/we-need-channels-intro-to-csp:
CSP is a formal language for describing patterns of interaction in concurrent systems
The library used in the following example is CISPY
I am new to this concept. It's not widely use in Javascript world, because of well established alternatives like Redux-Saga.
To dive directly into the subject, I suggest you to give an eye to the following sample.
A specific task is assigned to three workers.
Those tasks are accomplished in order in asynchronous mode.
The main idea of CSP, is the ability to synchronize tasks using channels.
That resssembles to the patterm Observer/Subscriber, but there are subtils differences and they are not incompatible.
In CSP you put data in a channel and you take data from channel.
Those two operations are blocking ones.
If there is nothing to take, the process block
You can't put data in an 'occupied' channel.
That's why we can write 'while(true)' loops without any problems.
The workers can't accomplish anything, before the scheduler receives the number of the task to dispatch.
The scheduler process and the worker process are synchronized.
Note that there is no global variables.
const { go, put, take, sleep, chan } = cispy;
let random = () => Math.floor(Math.random() * 1000 + 800);
const schedchannel = chan();
const workerchannel = chan();
const report = document.getElementById('report'); // Assurez-vous que cet élément existe dans votre HTML
// Fonction pour récupérer un worker aléatoire
async function fetchWorker() {
try {
let req = await fetch("https://randomuser.me/api/");
let resp = await req.json();
let workerinfo = resp.results[0];
return {
name: `${workerinfo.name.first} ${workerinfo.name.last}`,
photo: workerinfo.picture.thumbnail
};
} catch (e) {
console.error("Erreur fetchWorker :", e);
return {
name: "Worker par défaut",
photo: "https://via.placeholder.com/60"
};
}
}
// Fonction pour simuler une tâche
async function taskRunner() {
let delay = random();
await sleep(delay);
return delay;
}
// Définition des tâches
const tasks = [
{
task: "init tasks",
run: taskRunner,
worker: fetchWorker
},
{
task: "assemble the product",
run: taskRunner,
worker: fetchWorker
},
{
task: "put the product in box",
run: taskRunner,
worker: fetchWorker
},
{
task: "send the product",
run: taskRunner,
worker: fetchWorker
}
];
// Scheduler
go(async () => {
let numproduct = 0;
console.log("Start Task");
while (true) {
let numtask = await take(schedchannel);
let nexttask = (numtask + 1) % tasks.length; // Rotation sur toutes les tâches
if (nexttask === 0) numproduct++; // Incrémente après un cycle complet
await put(workerchannel, {
task: tasks[nexttask],
numtask: nexttask,
numproduct: numproduct
});
}
});
// Worker
go(async () => {
while (true) {
let taskpayload = await take(workerchannel);
const { task, numtask, numproduct } = taskpayload;
try {
let worker = await task.worker(); // Appelle la fonction asynchrone
let delay = await task.run(); // Appelle la fonction asynchrone
reportTask(worker, task, numproduct, delay);
} catch (e) {
console.error("Erreur dans le worker :", e);
reportTask(
{ name: "Erreur", photo: "https://via.placeholder.com/60" },
task,
numproduct,
"Erreur"
);
}
await put(schedchannel, numtask);
}
});
// Affichage du rapport
function reportTask(worker, task, numproduct, delay) {
report.innerHTML = `
<div class="item"><span class="title">Product :</span> ${numproduct}</div>
<div class="item"><span class="title">Worker :</span> <img src="${worker.photo}" height="60px" />${worker.name}</div>
<div class="item"><span class="title">Task :</span> ${task.task}</div>
<div class="item"><span class="title">Delay :</span> ${delay}ms</div>
`;
}
// Démarrage
function start() {
put(schedchannel, -1);
}
start();
You can test the code here : CSP-Demo
Top comments (0)