Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for event in node js

How can I wait for an event in node js? I'm developing a bpmn workflow and I have to execute the event step by step.The server is compounded by several scripts and each script is an event, like this:

'use strict';
const Bpmn = require('bpmn-engine');
const processXml = `
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <process id="theProcess" isExecutable="true">
    <startEvent id="start" />
    <exclusiveGateway id="decision" />
    <endEvent id="RFID_ERRATO" />
    <endEvent id="RFID=M1" />
    <sequenceFlow id="flow1" sourceRef="start" targetRef="decision" />
    <sequenceFlow id="flow2" sourceRef="decision" targetRef="RFID_ERRATO">
      <conditionExpression xsi:type="tFormalExpression" 
language="JavaScript"><![CDATA[
      this.variables.input != "M1"
      ]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="decision" targetRef="RFID=M1">
      <conditionExpression xsi:type="tFormalExpression" 
language="JavaScript"><![CDATA[
      this.variables.input = "M1" 
      ]]></conditionExpression>
    </sequenceFlow>
  </process>
</definitions>`;

const engine = new Bpmn.Engine({
  name: 'exclusive gateway example1',
  source: processXml
});

engine.once('end', (definition) => {
  if (definition.getChildActivityById('RFID_ERRATO').taken) throw new 
Error('<RFID_ERRATO> was not supposed to be taken, check your input');
  console.log('TAKEN RFID=M1', 
definition.getChildActivityById('RFID=M1').taken);
});


function sendEvent(value){
  engine.execute({
  variables: {
    input: value
  }
}, (err, definition) => {
  console.log(engine.getState())
});
}

var i = 0;
//hello.js
module.exports = (req, res, next) => {
  //res.header('X-Hello', 'World')
  //console.log(req);
  if(!i++){
    sendEvent(req.body.rfid);
  }
  console.log(engine.getState())
  next()
}

(I'm using these modules https://www.npmjs.com/package/bpmn-engine https://www.npmjs.com/package/json-server). The server is started writing on the command line "json-server db.json --middlewares ./script1.js ./script2.js" and then I call the request post sending the data over the server, only one time. The problem is that all the events reply at the only first request sequentially. I want that the first script/event reply at the first request while the second event is waiting,and when the second request is sent,the following script perform it,and so on. It is possible?

like image 415
Ondescone Avatar asked Apr 08 '26 03:04

Ondescone


1 Answers

To wait and then do something, you need to run the code in an asynchronous way, there's a lot of good approaches for that.

The most common is the promise, a promise will gets the return or a error from an asynchronous code. Basic example(from Mozilla Developers):

let myFirstPromise = new Promise((resolve, reject) => {
  // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
  // In this example, we use setTimeout(...) to simulate async code. 
  // In reality, you will probably be using something like XHR or an HTML5 API.
  setTimeout(function(){
    resolve("Success!"); // Yay! Everything went well!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage is whatever we passed in the resolve(...) function above.
  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
  console.log("Yay! " + successMessage);
});

The "thing" in asynchronous is that we'll do something and then we'll do something, this then is doing what we need and don't have in a sync code.

There's a lot of npm packages that can help us to do that too, like async-waterfall that will run the functions in series, example from their github:

/* basic - no arguments */
waterfall(myArray.map(function (arrayItem) {
  return function (nextCallback) {
    // same execution for each item, call the next one when done
    doAsyncThingsWith(arrayItem, nextCallback);
}}));

/* with arguments, initializer function, and final callback */
waterfall([function initializer (firstMapFunction) {
    firstMapFunction(null, initialValue);
  }].concat(myArray.map(function (arrayItem) {
    return function (lastItemResult, nextCallback) {
      // same execution for each item in the array
      var itemResult = doThingsWith(arrayItem, lastItemResult);
      // results carried along from each to the next
      nextCallback(null, itemResult);
}})), function (err, finalResult) {
  // final callback
});

It will run an Array.map of functions in series, avoiding a good enemy when we work with async codes, the callback hell.

So async code will let you wait for an event cause it let's you do something and then do another thing with the results.

like image 175
Diogo Avatar answered Apr 09 '26 17:04

Diogo