When integrating a Progress Corticon decision service into your JavaScript applications, handling asynchronous (async) operations correctly is critical, as decision services are an async function.
This blog presents three common async invocation patterns—using async/await propagation, a synchronous facade with an immediately invoked async function (IIAFE) and Promise chaining with .then()—all wrapped in a simple event-driven design that notifies when the decision service completes.
These patterns are demonstrated in this sample on the Corticon public Github.
As a historical note, decision services became asynchronous when we introduced support for service callout in Corticon V2.0.
Before we dive into the patterns, let’s look at the core async function that executes the Corticon rules engine—a common element to the three patterns presented below:
async function runDecisionService() {
try {
…
// Await the async decision service execution
const result = await window.corticonEngine.execute(payload, configuration);
…
} catch (e) {
alert('Unexpected exception executing the rules: ’ + e);
throw e;
}
}
This function uses modern async/await for clean, readable asynchronous calls and implements error handling. The code reads sequentially, and the execution is also sequential. That is, this function will return when the decision service has completed.
1. Async/Await Propagation — Async All the Way
You typically have a call stack of functions executing before the decision service is invoked. In this sample, we illustrate this condition with f1() calling f2() calling runDecisionService.
async function f1() {
console.log(“In f1 (async)”);
await f2();
}
async function f2() {
console.log(“In f2 (async)”);
await runDecisionService();
}
How it works:
Pros:
Cons:
2. Synchronous Facade with an IIAFE
function f1Sync() {
console.log(“In f1Sync (sync)”);
f2Sync();
console.log(“Exiting f1Sync before decision service completes”);
}
function f2Sync() {
console.log(“In f2Sync (sync)”);
(async () => {
console.log(“Invoking decision service inside IIAFE”);
const result = await runDecisionService();
console.log(“Decision service completed inside IIAFE”);
eventEmitter.emit(‘dsDone’, result);
})();
}
How it works:
Pros:
Cons:
3. Promise Chaining with .then()
function f1SyncWithThen() {
console.log(“In f1SyncWithThen (sync)”);
f2SyncWithThen();
console.log(“Exiting f1SyncWithThen before decision service completes”);
}
function f2SyncWithThen() {
console.log(“In f2SyncWithThen (sync)”);
console.log(“Invoking decision service with .then()”);
runDecisionService()
.then(result => {
console.log(“Decision service completed with .then()”);
eventEmitter.emit(‘dsDone’, result);
})
.catch(error => {
console.error(“Error in decision service (with .then()):”, error);
alert("Error executing the decision service: " + error);
});
console.log(“Proceeding after invoking decision service with .then()”);
}
How it works:
Pros:
Cons:
The sample on the Corticon public Github page also introduces a simple EventEmitter to allow your app to respond when the decision service completes:
class EventEmitter {
constructor() { this.events = {}; }
on(event, listener) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(listener);
return this;
}
emit(event, …args) {
if (!this.events[event]) return false;
this.events[event].forEach(listener => listener(…args));
return true;
}
}
const eventEmitter = new EventEmitter();
// Listen for decision service completion event
eventEmitter.on(‘dsDone’, (result) => {
console.log(“Event: Decision Service Completed”);
// Further UI updates or workflows can be triggered here
});
This pattern decouples your UI or business logic from the async decision service invocation, promoting clean separation and easier maintenance.
Here is a table summarizing the pros and cons of the patterns as presented in the sample on the Corticon public Github page:
Pattern | When to Use | Pros | Cons |
Async/Await Propagation | New projects or full async control | Readable, linear flow; easy error handling | Async "coloring" spreads through code |
Synchronous Facade (IIAFE) | Integration into legacy or synchronous APIs | Keeps call stack sync; event notifications | More complex; no direct return values |
Promise Chaining (.then()) | Preferring classic Promises or older envs | Familiar; works everywhere | Less readable with multiple async steps |
Take the next step and enroll in free training, or learn more about Corticon.js.
Thierry Ciot is a Software Architect on the Corticon Business Rule Management System. Ciot has gained broad experience in the development of products ranging from development tools to production monitoring systems. He is now focusing on bringing Business Rule Management to Javascript and in particular to the serverless world where Corticon will shine. He holds two patents in the memory management space.
Subscribe to get all the news, info and tutorials you need to build better business apps and sites