Asynchronous GlideAjax Explained: A Comprehensive Guide






Asynchronous GlideAjax Explained – Mastering ServiceNow Performance


Asynchronous GlideAjax Explained: Mastering ServiceNow Performance

In the world of ServiceNow development, performance and user experience are paramount. Slow-loading forms, unresponsive interfaces, and lengthy processing times can quickly frustrate users and hinder productivity. One of the most powerful tools in a developer’s arsenal for tackling these issues is GlideAjax, and specifically, its asynchronous implementation.

Many developers, especially those new to ServiceNow, might be familiar with making server calls, but understanding the nuances of asynchronous operations can be the difference between a clunky application and a blazing-fast, seamless user experience. This article will dive deep into asynchronous GlideAjax, demystifying its mechanics, showcasing its practical applications, and even touching upon why it’s a hot topic in ServiceNow interviews.

What is GlideAjax?

Before we get to the ‘asynchronous’ part, let’s briefly define GlideAjax. At its core, GlideAjax is a client-side JavaScript API in ServiceNow that allows your Client Scripts to communicate with the server. Think of it as a messenger service: your browser (the client) wants to ask the ServiceNow server for some information or to perform a specific task, and GlideAjax facilitates that conversation.

Traditionally, GlideAjax was often used in a synchronous manner, meaning the browser would wait for the server’s response before allowing the user to interact with anything else. This is akin to making a phone call and holding the line, unable to do anything else until the other person speaks. While simple, this approach can lead to frozen browser windows and a poor user experience, especially if the server takes a while to respond.

The Power of Asynchronous Operations

This is where asynchronous GlideAjax shines. Instead of waiting for the server’s reply, an asynchronous call sends the request to the server and immediately allows the user to continue interacting with the application. The response from the server is then handled later, via a callback function, when it arrives. This is like sending a text message: you send it, and then you can go about your day. You get a notification when a reply comes in, and you can address it then.

The benefits of this approach are significant:

  • Improved User Experience: The most obvious benefit. The UI remains responsive, preventing users from feeling like the system has frozen.
  • Increased Efficiency: Users can perform other actions while waiting for the server response, leading to quicker task completion.
  • Better Resource Utilization: The browser isn’t tied up waiting, allowing it to handle other tasks more efficiently.

How Asynchronous GlideAjax Works: The Mechanics

The magic of asynchronous GlideAjax lies in how it’s implemented using JavaScript’s non-blocking nature and ServiceNow’s framework. Here’s a breakdown of the typical flow:

1. The Client Script: Initiating the Request

Everything starts with a Client Script on the ServiceNow form or client-side context. You’ll typically use the g_form.getReference() method for simple record lookups, but for more complex server-side logic, you’ll use GlideAjax directly.

Let’s look at the standard structure for an asynchronous GlideAjax call:


function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue === '') {
        return;
    }

    var ga = new GlideAjax('MyScriptInclude'); // Specify your Script Include name
    ga.addParam('sysparm_name', 'myFunctionName'); // The function to call in the Script Include
    ga.addParam('sysparm_user_id', g_form.getValue('requested_for')); // Pass parameters

    ga.getXML(ajaxResponseHandler); // The core of asynchronous operation!
}

function ajaxResponseHandler(response) {
    // This function is called when the server responds
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.setValue('some_field', answer); // Use the data returned from the server
}
    

Let’s break down the key components:

  • var ga = new GlideAjax('MyScriptInclude');: This line instantiates the GlideAjax object. The argument `’MyScriptInclude’` is the name of the Script Include on the server that will handle the request. Script Includes are reusable server-side JavaScript libraries in ServiceNow.
  • ga.addParam('sysparm_name', 'myFunctionName');: This is a crucial parameter. It tells the Script Include which specific function to execute. ServiceNow automatically processes these parameters.
  • ga.addParam('sysparm_user_id', g_form.getValue('requested_for'));: You can add any number of parameters to pass data from the client to the server. These are prefixed with `sysparm_`.
  • ga.getXML(ajaxResponseHandler);: This is the magic method that makes the call asynchronous. Instead of waiting for a direct return value, it takes a callback function (`ajaxResponseHandler` in this case) as an argument. This function will be executed only when the server sends back a response.

2. The Server Script Include: Handling the Request

On the server-side, you need a Script Include that matches the name provided in the GlideAjax call. This Script Include will contain the logic to process the request and return data.

Here’s a corresponding Script Include:


var MyScriptInclude = Class.create();
MyScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    myFunctionName: function() {
        // Retrieve parameters passed from the client
        var userId = this.getParameter('sysparm_user_id');

        // Perform server-side logic (e.g., query a table)
        var gr = new GlideRecord('sys_user');
        if (gr.get(userId)) {
            var userName = gr.getValue('name');
            // Return the answer
            return userName;
        }
        return ''; // Return empty if user not found
    },

    type: 'MyScriptInclude'
});
    

Let’s dissect this server-side script:

  • var MyScriptInclude = Class.create();: Defines a new class.
  • MyScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, { ... });: This is essential. Your Script Include must extend `AbstractAjaxProcessor` to be usable with GlideAjax.
  • myFunctionName: function() { ... }: This is the function that the client script called using `sysparm_name`. The name here must match the value passed to `sysparm_name`.
  • this.getParameter('sysparm_user_id');: This is how you retrieve parameters sent from the client script. The parameter name (without `sysparm_`) is used here.
  • return userName;: The value returned by this function is what gets sent back to the client’s `ajaxResponseHandler`.
  • type: 'MyScriptInclude': This is a mandatory property for Script Includes that extend `AbstractAjaxProcessor`.

3. The Callback: Handling the Response

The `ajaxResponseHandler` function on the client-side receives an `XMLDocument` object as its argument (`response`). You can then parse this response to extract the data returned from the server.

In our example:

  • var answer = response.responseXML.documentElement.getAttribute("answer");: The value returned from the server script is automatically wrapped in an attribute named `answer` within the XML response. We extract this value.
  • g_form.setValue('some_field', answer);: This line takes the retrieved `answer` and populates a field on the current form.

This asynchronous nature ensures that while the server is processing the request and sending back data, the user can still type in other fields, click buttons, or scroll through the form without any lag.

Real-World Examples of Asynchronous GlideAjax

Let’s explore some practical scenarios where asynchronous GlideAjax is invaluable:

Example 1: Populating Dependent Fields on an Incident Form

Imagine an Incident form where selecting a Configuration Item (CI) should automatically populate fields like “CI Class” and “Support Group”.

  • Client Script (onChange of Configuration Item):
  • 
    function onChange(control, oldValue, newValue, isLoading) {
        if (isLoading || newValue === '') {
            return;
        }
    
        var ga = new GlideAjax('CIUtils'); // Custom Script Include
        ga.addParam('sysparm_name', 'getCIDetails');
        ga.addParam('sysparm_ci_id', newValue);
    
        ga.getXML(function(response) { // Anonymous callback function
            var answer = response.responseXML.documentElement.getAttribute("answer");
            if (answer) {
                var ciDetails = JSON.parse(answer); // Assuming server returns JSON
                g_form.setValue('cmdb_ci_class', ciDetails.ci_class);
                g_form.setValue('assignment_group', ciDetails.support_group);
            } else {
                g_form.setValue('cmdb_ci_class', '');
                g_form.setValue('assignment_group', '');
            }
        });
    }
            
  • Script Include (CIUtils):
  • 
    var CIUtils = Class.create();
    CIUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
        getCIDetails: function() {
            var ciId = this.getParameter('sysparm_ci_id');
            var gr = new GlideRecord('cmdb_ci');
            if (gr.get(ciId)) {
                var responseObj = {
                    ci_class: gr.getValue('sys_class_name'),
                    support_group: gr.getValue('support_group') // Assuming this field exists on CI
                };
                return JSON.stringify(responseObj); // Return as JSON string
            }
            return '';
        },
        type: 'CIUtils'
    });
            

Why asynchronous here? As the user selects a CI, we don’t want the form to freeze while we look up its class and support group. The user should be able to continue filling out other details like the Short Description or Description immediately.

Example 2: Validating User Input Against Business Rules

Consider a scenario on a custom application where a user enters a “Project Code.” You want to check if this Project Code is valid and belongs to an active project before proceeding.

  • Client Script (onChange of Project Code):
  • 
    function onChange(control, oldValue, newValue, isLoading) {
        if (isLoading || newValue === '') {
            g_form.clearMessages();
            return;
        }
    
        var ga = new GlideAjax('ProjectValidation');
        ga.addParam('sysparm_name', 'isValidProject');
        ga.addParam('sysparm_project_code', newValue);
    
        ga.getXML(function(response) {
            var isValid = response.responseXML.documentElement.getAttribute("answer");
            if (isValid === 'true') {
                g_form.clearMessages(); // Clear any previous error messages
                // Optionally do something if valid, like enable a button
            } else {
                g_form.addErrorMessage('The Project Code "' + newValue + '" is invalid or inactive.');
                g_form.setValue('project_code', ''); // Clear the invalid input
            }
        });
    }
            
  • Script Include (ProjectValidation):
  • 
    var ProjectValidation = Class.create();
    ProjectValidation.prototype = Object.extendsObject(AbstractAjaxProcessor, {
        isValidProject: function() {
            var projectCode = this.getParameter('sysparm_project_code');
            var gr = new GlideRecord('u_project'); // Assuming a 'u_project' table
            gr.addQuery('u_project_code', projectCode);
            gr.addQuery('u_status', 'Active'); // Check for active status
            gr.query();
            return gr.hasNext(); // Returns true if a matching record is found, false otherwise
        },
        type: 'ProjectValidation'
    });
            

Why asynchronous here? Validating user input should not halt the user’s workflow. They should be able to type, and if an error is found, a non-blocking message appears, allowing them to correct it without the form becoming unresponsive.

Troubleshooting Asynchronous GlideAjax

Even with well-written code, issues can arise. Here are common troubleshooting steps for asynchronous GlideAjax:

Common GlideAjax Troubleshooting Steps

  • Check the Browser Console: This is your first line of defense. Open your browser’s developer console (usually F12) and look for JavaScript errors. Network tab can show requests being sent and their responses.
  • Verify Script Include Name: Ensure the Script Include name in new GlideAjax('YourScriptInclude'); exactly matches the name of your server-side Script Include. Case sensitivity matters!
  • Confirm Function Name (`sysparm_name`): Double-check that the value passed to `sysparm_name` in `addParam()` matches the function name in your Script Include.
  • Parameter Mismatch: Are you passing parameters correctly from the client? Are you retrieving them correctly on the server using this.getParameter()? The parameter name (without `sysparm_`) must match.
  • Script Include `type` Property: For Script Includes used with GlideAjax, ensure they extend `AbstractAjaxProcessor` and have the `type: ‘YourScriptIncludeName’` property.
  • Server-Side Errors: If the client-side console shows no errors, the issue might be on the server. Use gs.log('Your message'); within your Script Include to debug. Check the System Logs (syslog table) for any uncaught exceptions originating from your Script Include.
  • Response Handling: In the `ajaxResponseHandler` (or callback function), ensure you are correctly parsing the `response.responseXML` object. If you are returning JSON from the server, make sure JSON.parse() is used and that the server is actually returning valid JSON.
  • Incorrect `getXML` vs. `getXMLAnswer` vs. `post`:
    • getXML(): Used for asynchronous calls where you handle the full XML response. Ideal for most modern use cases.
    • getXMLAnswer(): A convenience method for asynchronous calls that only returns the `answer` attribute from the XML. It’s less common now.
    • post(): For asynchronous POST requests. Less common for simple data retrieval.

    Ensure you are using the appropriate method and handling its return correctly.

  • Caching Issues: Sometimes, browser or server-side caching can cause unexpected behavior. Try clearing your browser cache or performing a hard refresh (Ctrl+Shift+R or Cmd+Shift+R).
  • Security Rules: Ensure that the user running the client script has the necessary permissions to access the data being retrieved on the server.

Interview Relevance: Why Asynchronous GlideAjax is a Key Topic

When you’re interviewing for a ServiceNow developer role, demonstrating a solid understanding of asynchronous GlideAjax is crucial. Interviewers want to see that you can:

Interview Insights: Asynchronous GlideAjax

  • Problem-Solving Ability: Can you identify performance bottlenecks and propose solutions? Asynchronous GlideAjax is a prime example of improving user experience.
  • Technical Depth: Do you understand the difference between synchronous and asynchronous operations? Can you explain how JavaScript’s event loop and ServiceNow’s framework enable this?
  • Best Practices: Do you know how to write efficient, maintainable, and secure GlideAjax calls? This includes proper error handling, parameter passing, and server-side logic design.
  • Debugging Skills: Can you articulate your troubleshooting process when a GlideAjax call fails? Mentioning browser consoles, server logs, and step-by-step verification is important.
  • API Knowledge: A deep understanding of client-side APIs (GlideAjax, g_form) and server-side APIs (GlideRecord, AbstractAjaxProcessor) is expected.
  • Performance Optimization: How do you ensure your ServiceNow applications are fast? Asynchronous GlideAjax is a cornerstone of performance tuning.
  • Example Scenarios: Be prepared to walk through real-world examples like the ones discussed above, explaining why you chose asynchronous GlideAjax for that specific use case.

Expect questions like:

  • “Explain the difference between synchronous and asynchronous GlideAjax. When would you use each?” (Hint: You’d almost always prefer asynchronous unless there’s a very specific, rare reason not to).
  • “How do you handle errors in an asynchronous GlideAjax call?”
  • “Describe a situation where you used GlideAjax to improve form performance.”
  • “Walk me through the components of a GlideAjax request and response.”

Beyond the Basics: Advanced Considerations

  • JSON for Complex Data: For returning multiple pieces of data, returning a JSON string from the server and parsing it on the client (`JSON.parse()`) is generally cleaner and more scalable than trying to extract multiple `answer` attributes or using multiple GlideAjax calls.
  • Error Handling: Implement robust error handling in your callback functions. What happens if the server script throws an error or returns unexpected data?
  • Timeouts: While not directly part of GlideAjax, consider implementing client-side timeouts for critical operations if you’re concerned about indefinitely long server responses.
  • Cancellation: For very long-running operations, you might explore ways to cancel pending GlideAjax requests if the user navigates away or performs an action that makes the original request moot.

Conclusion

Asynchronous GlideAjax is not just a feature; it’s a fundamental concept for building responsive and performant applications within ServiceNow. By understanding how to effectively leverage client-server communication without blocking the user interface, you can dramatically enhance the user experience, reduce perceived loading times, and build more sophisticated client-side logic.

Mastering asynchronous GlideAjax will not only make your ServiceNow development skills shine but also significantly improve the usability and efficiency of the applications you build. So, the next time you need to fetch data or trigger server-side logic from your Client Scripts, remember the power of going asynchronous!


Scroll to Top