JavaScript Promises in APEX
As I was reading the APEX 5.1 API documentation the other day, I noticed something pretty interesting under the apex.server namespace.
apex.server.process and apex.server.plugin are now returning JavaScript Promises.
apex.server.plugin( pAjaxIdentifier, pData, pOptions ) → Promise
apex.server.process( pName, pData, pOptions ) → Promise
What are JavaScript Promises?
A JavaScript Promise is essentially an object that returns asynchronous code.

Let's take a step back for a second...
Synchronous vs asynchronous
Synchronous coding always runs the code from top to bottom.
- Pros: It's easy and logical to read from the human eye.
- Cons: It's slow and it's blocking your user's interactions when the code is running.
Asynchronous coding allows the code to continue to run when longer processes are launched.
- Pros: It's much faster and non-blocking.
- Cons: It inverses the order in which a human reads the code.
Just remember this: Synchronous is blocking. Asynchronous is non-blocking. Asynchronous is good. Synchronous is bad.
Using Callbacks
Asynchronous code is achieved by using callbacks. Let's have a look at the following code:
console.log(1);
apex.server.process(
"some_ajax", {}, {
success: function(data) {
console.log(2);
}
}
);
console.log(3);
Reading from top to bottom in a synchronous way, we would expect the outcome to be:
1
2
3
But apex.server.process is not synchronous, so while it does whatever's in "some_ajax", the code continues to run, resulting in the following outcome:
1
3
2

Yeah... So let's just continue to nest the code inside the callbacks.
apex.server.process(
"ajax1", {}, {
success: function(data) {
console.log(1);
apex.server.process(
"ajax2", {}, {
success: function(data) {
console.log(2);
apex.server.process(
"ajax3", {}, {
success: function(data) {
console.log(3);
}
}
);
}
}
);
}
}
);
That my friends, is what we call "Callback Hell"...

Unravelling the Callbacks
With Promises, we get the best of both worlds by benefiting from the fast and non-blocking asynchronous code, but by writing it in a readable top-to-bottom way.
Let's follow the demo below.
Setup
A demo is available here, directly on the login page. Make sure to open up your browser's console to see what's going on.
APEX - Ajax Callbacks
We will be creating 3 Ajax Callbacks.

ajax1
Simulates a 1 second process and returns a JSON object.
declare
l_now timestamp := systimestamp;
l_end_time timestamp;
begin
l_end_time := l_now + numtodsinterval (1, 'second');
while(l_end_time > l_now) loop
l_now := systimestamp;
end loop;
apex_json.open_object;
apex_json.write('success', true);
apex_json.write('x01', apex_application.g_x01);
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write('success', false);
apex_json.write('message', sqlerrm);
apex_json.close_object;
end;
ajax2
Simulates a 2 seconds process and returns a JSON object.
declare
l_now timestamp := systimestamp;
l_end_time timestamp;
begin
l_end_time := l_now + numtodsinterval (2, 'second');
while(l_end_time > l_now) loop
l_now := systimestamp;
end loop;
apex_json.open_object;
apex_json.write('success', true);
apex_json.write('x01', apex_application.g_x01);
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write('success', false);
apex_json.write('message', sqlerrm);
apex_json.close_object;
end;
ajax_error
Simulates a failed process by raising an error.
raise_application_error(-20001, sqlerrm);
APEX - Page Properties
The code below is added to the page properties, under the Function and Global Variable Declaration section.
// Logs an error when a Promise is rejected
var displayError = function(error) {
console.error("Promise is rejected:", error);
};
// Function returning a Promise (ajax1)
var promise1 = function(param) {
return apex.server.process(
"ajax1", {
x01: param
}
);
};
// Function returning a Promise (ajax2)
var promise2 = function(param) {
return apex.server.process(
"ajax2", {
x01: param
}
);
};
// Function returning a Promise (ajax_error)
var promiseError = function() {
return apex.server.process(
"ajax_error", {}
);
};
Creating a Promise
As shown above, we'll encapsulate all apex.server.process inside functions and we'll simply return the object. As I mentioned at the beginning, apex.server.process returns a Promise, so our functions will be returning Promises as well.
Statuses
A Promise has 3 possible statuses:
- Pending: When a Promise is invoked, it's set to Pending. The data hasn't returned yet.
- Resolved: A Promise is Resolved when the data came back successfully.
- Rejected: A Promise is Rejected when the data came back with errors.
Once a Promise is resolved or rejected, it can never change to another status again.
How to use a Promise
then
The code below is added to the page properties, under the Execute when Page Loads section.
// Chaining the promises
// Simulating a synchronous process chain
promise1(2)
.then(function(data) {
console.log("promise1 is resolved:", data);
// passing the data from promise1 to promise2
// and doubling the value of x01
return promise2(data.x01 * 2);
}, displayError)
.then(function(data) {
console.log("promise2 is resolved:", data);
return promiseError();
}, displayError)
.then(function(data) {
console.log("promiseError is resolved (Never gonna happen...):", data);
}, displayError);
What happens here?
- We invoke
promise1with a parameter of2 - If
promise1succeeds, we display the data. If it fails we display the error (displayError). - Then we invoke
promise2. We use the data frompromise1and pass it topromise2. - If
promise2succeeds, we display the data. If it fails we display the error (displayError). - Then we invoke
promiseError. promiseErrorwill never succeed, so we display the the error (displayError).
all
The code below is added to the page properties, under the Execute when Page Loads section.
// Executing all the promises at the same time
// Waiting for all of them to return
Promise.all([promise1(2), promise2(4)])
.then(function(data) {
console.log("All Promises are resolved:", data);
}).catch(displayError);
What happens here?
- We invoke
promise1andpromise2at the same time. - It waits until all Promises have returned.
- If all Promises succeed, we display all the data (as an array of objects).
- If one or more Promise fails, we display the error (
displayError).
race
The code below is added to the page properties, under the Execute when Page Loads section.
// Executing all the promises at the same time
// Waiting for the **first** one to return
Promise.race([promise1(2), promise2(4)])
.then(function(data) {
console.log("Fastest Promise is resolved:", data);
}).catch(displayError);
What happens here?
- We invoke
promise1andpromise2at the same time. - It waits until the first Promise has returned.
- If that first Promise succeeds, we display it's data.
- If that first Promise fails, we display the error (
displayError).
catch
Notice the .catch at the bottom of the previous example. That is simply catch the error that occurs during one of more promise. Just like a regular try {} catch {} would do.
Final Result
When all the code above is launched on page load, here's what we get:

What happens here?
- The 3 code blocks launched simultaneously* (
promise1,Promise.allandPromise.race). - promise1 and Promise.race returned simultaneously after 1 second.
- promise2 launched.
- Promise.all returned after 2 seconds.
- promise2 returned after 3 seconds (1 second for promise1 and 2 seconds for promise2).
- promiseError launched.
- promiseError failed.
*Almost simultaneously...
Perhaps not a surprise, but this whole snippet of code also works on APEX 5.0, because 5.0's apex.server.process is returning a jqXHR object, which implements the Promise interface...
Damn, I wish I knew this earlier...!