logo

NJP

How to write GlideAjax like a pro

The SN Nerd · Sep 03, 2025 · article

This article is relevant for the following ServiceNow releases: washington dc, Xanadu.


If you’ve ever built client-side scripts in ServiceNow that need to reach across to the server for data or complex logic, then you’ve likely encountered GlideAjax—the essential API that acts as the communication bridge between client and server. GlideAjax enables your client scripts to send requests asynchronously to server-side Script Includes without forcing a full page reload, saving users’ time and making your applications feel much snappier.

But don’t be fooled—scripting with GlideAjax is trickier than it looks. Because it involves both client and server components, and asynchronous callbacks, it can be a minefield for performance pitfalls, timing bugs, or cryptic errors if not implemented carefully. Mastering GlideAjax requires understanding its architecture, properly structuring your requests and responses, and handling asynchronous responses elegantly.

In this guide, I’ll walk you through writing error-free GlideAjax code like a seasoned pro. You’ll see how to leverage GlideAjax efficiently and avoid common mistakes that trip up even experienced developers. By the end, you’ll confidently call server methods from your client scripts, passing parameters and processing multi-value responses effortlessly.

As a practical example, we’ll build a script that calls a server-side Script Include to retrieve reports associated with a user and populate them into a client-side List variable. This real-world use case illustrates the power and subtlety of GlideAjax and how to wield it cleanly for maximum performance and reliability.

Populating a Reference list variable based on a given user

Ready to glide into pro-level ServiceNow scripting? Let’s dive in.

Check yourself before you wreck yourself

With every family release, we see more tools that eliminate the need for code writing. You might think you know them all – but do you? Before writing any code, see my guide Client Side Data Retrieval – The Ultimate Guide to check for alternative methods.

If we check my handy table, we can see the appropriate pattern for this use case is GlideAjax /w Client Callable Script Include.

In this case we won’t be wrecking ourselves, but it is important to stay vigilant and aware of the other tools available to you.

Create client logic with mock data

Create your client script first. Separate your logic to populate the ‘Reports’ variable into its own function, which the GlideAjax callback function will use later. Use some static mock data to test that it will work conceptually.

function onChange(control, oldValue, newValue, isLoading) {
if (newValue == '') {
g_form.clearValue('report_s');
return;
}

// Step 1 - add client side code and test with mock data
processData("02826bf03710200044e0bfc8bcbe5d7f,0382abf03710200044e0bfc8bcbe5d42");
//processData("");
function processData(userSysIDCSV) {
if (userSysIDCSV == '') {
g_form.showFieldMsg('report_s', 'User has no reports', 'warning');
} else {
g_form.setValue('report_s', userSysIDCSV);
}
}

}

Create server-side logic using GlideAjax

Create a script include with the client callable option selected. Consider suffixing with Ajax as part of your naming convention.

Break down your logic into functions so it can be unit tested server-side. When things get complicated – you’ll thank me later.

var GetUsersReportsAjax = Class.create();
GetUsersReportsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// Step 1: server side function
getUserReports: function(userSysId) {
var answer = '';
var userSysIdArray = [];
var userGR = new GlideRecord('sys_user');
userGR.addQuery('manager',userSysId);
userGR.query();
while(userGR.next()) {
userSysIdArray.push(userGR.getValue('sys_id'));
}

    answer = userSysIdArray.join(",");

    return answer;
},

type: 'GetUsersReportsAjax'

});

Break down your logic into functions and unit test using Background scripts or Xplore.

var test = new GetUsersReportsAjax();
var result = test.getUserReports('06826bf03710200044e0bfc8bcbe5d41');
gs.info(result);

*** Script: 02826bf03710200044e0bfc8bcbe5d7f,0382abf03710200044e0bfc8bcbe5d42

Now add in the GlideAjax function, which our client script will call. Use the following pattern for error handling and include a optional parameter so you can easily test your inputs and error handling server-side.

// Step 2: client interface, error handling & standard response
getUserReportsAJAX: function(userSysId /for testing/) {
userSysId = userSysId || this.getParameter('sysparm_user_sysid'); // Param sent by client side
var answer = {success: false, data: ''};
try {
answer.data = this.getUserReports(userSysId);
answer.success = true;
} catch (e) {
gs.error('GetUsersReportsAjax error: ' + e.message);
answer['error'] = e.message;
}
return JSON.stringify(answer);
},

This can be tested as follows:

var test = new GetUsersReportsAjax();
var result = test.getUserReportsAJAX('06826bf03710200044e0bfc8bcbe5d41');
gs.info(result);

*** Script: {"success":true,"data":"02826bf03710200044e0bfc8bcbe5d7f,0382abf03710200044e0bfc8bcbe5d42"}

Bringing it together

Now the tricky bit – incorporating the GlideAjax API.

// Step 2 - add GlideAjax code
var ga = new GlideAjax("GetUsersReportsAjax"); // Name of client callable script include
ga.addParam('sysparm_name', 'getUserReportsAJAX'); // function to call
ga.addParam('sysparm_user_sysid', newValue); 
console.table(ga.params); // for debugging 
ga.getXMLAnswer(callback);

function callback(response) {
    var responseObj = JSON.parse(response);
    console.table(responseObj); // for debugging
    if (responseObj.hasOwnProperty('success') && responseObj.success) {
        // Your client logic here
        processData(responseObj.data);
    } else {
        var error = responseObj.hasOwnProperty('error') ? responseObj.error : "Unknown error";
        handleError(error);
    }
}

function handleError(error) {
    g_form.showFieldMsg('manager', error, 'error');
}

Using this process and the above as a template, you can eliminate hours of troubleshooting as you now have a simple repeatable process for creating GlideAjax. All you need to do is change the GlideAjax (ga) parameters and the rest is standard.

Success!

GlideAjax with error handling

Debugging your Client Script

Final Client Script

function onChange(control, oldValue, newValue, isLoading) {
if (newValue == '') {
g_form.clearValue('report_s');
return;
}

// Step 2 - add GlideAjax code
var ga = new GlideAjax("GetUsersReportsAjax"); // Name of client callable script include
ga.addParam('sysparm_name', 'getUserReportsAJAX'); // function to call
ga.addParam('sysparm_user_sysid', newValue); 
console.table(ga.params); // for debugging 
ga.getXMLAnswer(callback);

function callback(response) {
    var responseObj = JSON.parse(response);
    console.table(responseObj); // for debugging
    if (responseObj.hasOwnProperty('success') && responseObj.success) {
        // Your client logic here
        processData(responseObj.data);
    } else {
        var error = responseObj.hasOwnProperty('error') ? responseObj.error : "Unknown error";
        handleError(error);
    }
}

function handleError(error) {
    g_form.showFieldMsg('manager', error, 'error');
}

// Step 1 - add client side code and test with mock data
//processData("02826bf03710200044e0bfc8bcbe5d7f,0382abf03710200044e0bfc8bcbe5d42");
//processData("");
function processData(userSysIDCSV) {
    if (userSysIDCSV == '') {
        g_form.showFieldMsg('report_s', 'User has no reports', 'warning');
    } else {
        g_form.setValue('report_s', userSysIDCSV);
    }
}

}

Final Script Include

var GetUsersReportsAjax = Class.create();
GetUsersReportsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// Step 2: client interface, error handling & standard response
getUserReportsAJAX: function(userSysId /for testing/) {
userSysId = userSysId || this.getParameter('sysparm_user_sysid'); // Param sent by client side
var answer = {success: false, data: ''};
try {
answer.data = this.getUserReports(userSysId);
answer.success = true;
} catch (e) {
gs.error('GetUsersReportsAjax error: ' + e.message);
answer['error'] = e.message;
}
return JSON.stringify(answer);
},

// Step 1: server side function
getUserReports: function(userSysId) {
    var answer = '';
    var userSysIdArray = [];
    var userGR = new GlideRecord('sys_user');
    userGR.addQuery('manager',userSysId);
    userGR.query();
    while(userGR.next()) {
        userSysIdArray.push(userGR.getValue('sys_id'));
    }

    answer = userSysIdArray.join(",");

    return answer;
},

type: 'GetUsersReportsAjax'

});

The post How to write GlideAjax like a pro appeared first on The SN Nerd.

View original source

https://sn-nerd.com/2025/09/03/how-to-write-glideajax-like-a-pro/