DEV Community

artydev
artydev

Posted on

Exploring Communicating Sequential Processes in Javascript

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()


function fetchWorker () {
  return  async () => {
    let req = await fetch("https://randomuser.me/api/")
    let resp = await req.json()
    let workerinfo = (resp.results[0])
    return {name : workerinfo.name.first, photo : workerinfo.picture.thumbnail }
  }
} 

function taskRunner () {
 return  async (p) =>  { 
    let delay = random(); 
    await sleep(random()); 
    return delay 
  }
}

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
  while (true) {
    let numtask = await take(schedchannel)  
    let nexttask = (numtask % 3) + 1  
    if (nexttask == 1)  numproduct++  
    await put(workerchannel, { task : tasks[nexttask], numtask:nexttask, numproduct:numproduct }) 
  }
})

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>`  
}

// Worker
go (async () => {
  while (true) {
    let taskpayload = await take(workerchannel)
    const {task, numtask, numproduct} = taskpayload
    let worker = await task.worker()
    let delay = await task.run()
    reportTask (worker, task, numproduct, delay)
    await put(schedchannel, numtask)
  }
})

function start () {
  put(schedchannel, 0)   
}

start ()
Enter fullscreen mode Exit fullscreen mode

You can test the code here : CSP-Demo

Top comments (0)