← Home
🔥0 DAY
0 XP
Interview Prep · Client-Server Scripting

GLIDEAJAX
INTERVIEW.

GlideAjax is the bridge between client scripts and server logic in ServiceNow. Interviewers love asking about AbstractAjaxProcessor, how parameters flow across the boundary, callback handling, and why forms feel sluggish when GlideAjax is misused. Below are four lessons covering the server-side contract, client callbacks, structured data passing, and performance best practices — each with a runnable simulator trace.

Tap a lesson to inspect the simulator. For more server-side scripting, see the scenario-based scripting guide or practice GlideAjax timed questions.

  1. 1. AbstractAjaxProcessor — the server-side contract

    You're asked to build a server-side GlideAjax API that returns the count of open incidents for a given assignment group. What class do you extend, and what methods matter?

    How to answer

    • Extend AbstractAjaxProcessor in a Script Include — this is the only supported server-side base class for GlideAjax.
    • Use this.getParameter('parm_name') to read values sent from the client.
    • Return data with this.getParameterAnswer('result_key') so the client can read it in getXMLAnswer().
    • Keep the process() or processAnswer() method name matching what the client calls in getXMLWait() / getXMLAnswer().

    Reference script

    var GlideAjaxIncidentCount = Class.create();
    GlideAjaxIncidentCount.prototype = Object.extendsObject(AbstractAjaxProcessor, {
      getOpenCount: function() {
        var groupId = this.getParameter('sys_id');
        var gr = new GlideRecord('incident');
        gr.addQuery('assignment_group', groupId);
        gr.addQuery('state', '!=', 7); // not Closed
        gr.query();
        this.getParameterAnswer('count', gr.getRowCount());
      }
    });

    Pitfall

    Forgetting that getParameter() returns strings — comparing directly to a number with === fails. Cast with parseInt() or use == for loose equality when reading numeric parameters.

  2. 2. Client-side GlideAjax — callbacks and getXMLAnswer

    Write the client-side script that calls the server-side API and handles the response correctly. What's the difference between synchronous and async GlideAjax?

    How to answer

    • Instantiate GlideAjax with the Script Include name: new GlideAjax('GlideAjaxIncidentCount').
    • Add parameters with addParam('parm_name', value) — the first arg must match getParameter() on the server.
    • For async: call getXMLAnswer(callback) with a function that reads answer.getAttribute('answer').
    • For sync: call getXMLWait() which blocks the UI thread — acceptable only in onLoad Client Scripts or catalog client scripts where immediate data is needed.

    Reference script

    // Async — preferred, non-blocking
    var ga = new GlideAjax('GlideAjaxIncidentCount');
    ga.addParam('sysparm_name', 'getOpenCount');
    ga.addParam('sys_id', g_form.getValue('assignment_group'));
    ga.getXMLAnswer(function(answer) {
      var count = parseInt(answer, 10);
      g_form.setValue('u_open_count', count);
    });
    
    // Sync — blocks UI, use sparingly
    var ga = new GlideAjax('GlideAjaxIncidentCount');
    ga.addParam('sysparm_name', 'getOpenCount');
    ga.addParam('sys_id', g_form.getValue('assignment_group'));
    var xml = ga.getXMLWait();
    var answer = xml.documentElement.getAttribute('answer');

    Pitfall

    Using getXMLWait() inside a UI Action or onChange Client Script freezes the form for hundreds of milliseconds. Interviewers flag this as a performance anti-pattern — always prefer getXMLAnswer(callback) unless the requirement explicitly demands synchronous data before the user interacts.

  3. 3. Passing complex data — JSON encoding and limits

    You need to return an array of assignee names and their incident counts from a GlideAjax call. How do you pass structured data through a system designed for single key-value answers?

    How to answer

    • Serialize complex data to a JSON string on the server using JSON.stringify().
    • Pass the JSON string as a single parameter answer, then JSON.parse() it on the client.
    • Keep payloads small — GlideAjax answers travel through XML and large strings slow rendering.
    • For large datasets, return a sys_id list and query GlideRecord on the client, or use a Script Include + GlideRecord instead.

    Reference script

    // Server — AbstractAjaxProcessor
    getAssigneeSummary: function() {
      var gr = new GlideRecord('incident');
      gr.addQuery('state', '!=', 7);
      gr.query();
      var map = {};
      while (gr.next()) {
        var uid = gr.assigned_to.toString();
        map[uid] = (map[uid] || 0) + 1;
      }
      this.getParameterAnswer('summary', JSON.stringify(map));
    }
    
    // Client
    var ga = new GlideAjax('GlideAjaxIncidentCount');
    ga.addParam('sysparm_name', 'getAssigneeSummary');
    ga.getXMLAnswer(function(answer) {
      var summary = JSON.parse(answer);
      console.log(summary); // { '6816f79c…': 5, '62826f…': 3 }
    });

    Pitfall

    Trying to return a GlideRecord object or a direct JavaScript object via getParameterAnswer() — it stringifies to [object Object] or crashes. Always serialize to JSON on the server and deserialize on the client.

  4. 4. Performance best practices — batching, caching, and N+1

    A form loads slowly because an onLoad Client Script fires three separate GlideAjax calls for related reference field data. How do you fix it?

    How to answer

    • Batch multiple lookups into ONE server call — design a single AbstractAjaxProcessor method that returns all needed fields as a JSON payload.
    • Use getReference() on the client for single reference fields instead of GlideAjax — it caches and avoids a round-trip.
    • Debounce onChange handlers that trigger GlideAjax — rapid typing can spawn dozens of parallel requests.
    • Cache results in a client-side object (e.g., window._gaCache) when the same data is needed across multiple form sections.

    Reference script

    // BEFORE — 3 round trips
    var ga1 = new GlideAjax('LookupUser');
    ga1.getXMLAnswer(fn1);
    var ga2 = new GlideAjax('LookupDept');
    ga2.getXMLAnswer(fn2);
    var ga3 = new GlideAjax('LookupManager');
    ga3.getXMLAnswer(fn3);
    
    // AFTER — 1 round trip
    var ga = new GlideAjax('LookupBundle');
    ga.addParam('sysparm_name', 'getUserBundle');
    ga.addParam('sys_id', g_form.getValue('assigned_to'));
    ga.getXMLAnswer(function(answer) {
      var data = JSON.parse(answer);
      g_form.setValue('u_dept', data.department);
      g_form.setValue('u_manager', data.manager);
      g_form.setValue('u_location', data.location);
    });

    Pitfall

    Calling GlideAjax inside a while loop on the server is impossible — GlideAjax is client-only. If you need server-side batching, use a Script Include directly or a Scheduled Job, not GlideAjax.

Keep going

GlideAjax interlocks with Client Scripts, Script Includes, and Business Rules. Pair this guide with the glossary and timed drills to lock in the full picture.