In a Client Script, how to async await a return from a GlideAjax call made in a UI script function?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-18-2024 09:05 AM
Hi!
As a follow to my previous topic: "Script Includes but for Client-side code?"
I've started trying to implement my use case:
On a Catalog Item with three variables:
- VAT - read-write, number (by regex)
- Netto - read-write, number (by regex)
- Brutto - read-only, to be written to by g_form.setValue/else
I want to have the value for Brutto Var. be calculated by a GlideAjax script whenever either VAT or Netto change their values.
I can use two onChange Client Scripts to do that, but I like the "Don't Repeat Yourself" rule. So I thought I could try a challenge: how to not repeat the same GlideAjax call twice?
So thanks to @Sandeep Rajput 's suggestion, I have found that I can use a UI script for this purpose.
My plan would be to do the following:
- The onChange Catalog Client Script triggers:
- This Client Script would call the UI Script,
- The UI Script would in turn make a GlideAjax call to a Client-callable Script Include,
- The Script Include function returns the value to the UI Script via .getXMLAnswer,
- The UI Script would return the value to the Catalog Client Script, which would use g_form.setValue to set the value of the Brutto variable
- alternatively, the UI Script sets the value for Brutto on the Service Portal/backend Catalog Item request form
My current setup is approximately the following:
1. onChange Catalog Client Script on VAT/Netto executes
1a. The Client Script checks whether both the fields have a valid value
2. The CS makes a call to the GlideUIScripts API:
g_ui_scripts.getUIScript('VatCalcUiScript').then(function (uiscript) {
var calculatedBrutto = uiscript.calculateBrutto(parameters...);
console.debug('GlideUIScripts: calculatedBrutto=' + calculatedBrutto);
...
}
3. The VatCalcUtil UI Script checks whether the provided arguments are correct, and makes a GlideAjax call:
var ga = new GlideAjax('VatCalcUtils');
ga.addParam('sysparm_name', 'calculateBrutto');
ga.addParam(...)
console.debug('calculateBrutto: calling GlideAjax');
ga.getXMLAnswer(function (answer) {
var parsedAnswer = JSON.parse(answer);
console.debug('calculateBrutto: parsedAnswer = ' + parsedAnswer);
if (isNaN(parsedAnswer) || !answer) {
console.debug("calculateBrutto: Error encountered. Return is: " + answer);
return false;
}
console.debug('calculateBrutto: returning...');
return parseFloat(parsedAnswer);
}
But soon I encounter a perhaps obvious issue... The GlideAjax.getXMLAnswer call in the UI Script is run in a separate thread to the Client Script...
And so, the next line in the Client Script fires before the UI Script is done running:
I can't figure out if/how I could make a Promise call from the Client Script to a UI Script function. I also would prefer not to block the UI until I receive the GlideAjax return, so I don't want to switch away from .getXMLAnswer to something like getXMLWait.
It also seems that the UI script is ran in a different JS context - the g_form API is not available there.
What solutions can you think of? Perhaps I can approach this from an entirely another angle?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-19-2024 10:39 AM
@JeremiP Please refer to this example on GitHub https://gist.github.com/nfreeze/a9803d7f6049aa814d08de31eb80ee95 where the promise has been added into the UI Script function call itself.
Hope this helps.