- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-01-2023 12:15 AM
Hello Community!
I was wondering about the optional parameters of getXMLAnswer. The ServiceNow documentation shows it as
getXMLAnswer(Function callback, Object additionalParam, Object responseParam)
callback | Function | Callback function. The function receives the answer element of the response in XML format as an argument. |
additionalParam | Object | Optional. Name-value pair of additional parameters. |
responseParam | Object | Optional. Second argument for the callback function. |
From this I understood that the data I pass to responseParam would be available in the callback function. But I did not get it to work. I created a test script
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
var ga = new GlideAjax('ValueSetter');
ga.addParam('sysparm_name', 'returnDoubled');
ga.addParam('sysparm_number', newValue);
debugger;
ga.getXMLAnswer(setNumber, null, 'output_2');
}
function setNumber(ans, field_name) {
debugger;
if (ans) {
g_form.setValue(field_name, ans);
}
}
In the callback function field_name is undefined
I also tried looking into js_includes_sp.jsx with debugger and saw the following:
getXMLAnswer: function(callback) {
this.wantAnswer = true;
this.callbackFn = callback;
this.execute();
},
So how are these optional parameters supposed to work and how to use them?
Solved! Go to Solution.
- Labels:
-
script
-
Service Portal Development
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-01-2023 04:10 AM
That is a bit misleading as the function is not implemented everywhere (Core UI vs. Portal vs. Next) in the 3 parameter form.
But that is not a problem, you can "transmit" variables to the callback function using the closure "technique":
ga.getXMLAnswer(setNumber('output_2'));
function setNumber (field_name) {
return function callback (answer) {
g_form.setValue(field_name, answer);
};
}
Here getXMLAnswer will actually call ("inner"/returned) function callback, function that will have in its execution context variable field_name.
The same could be achieved using function binding too:
ga.getXMLAnswer(setNumber.bind({ field_name: 'output_2' }));
function setNumber (answer) {
g_form.setValue(this.field_name, answer);
}
When using the 1st technique one returns a function that will be called back by getXMLAnswer, when using the 2nd technique one defines/builds a new ad-hoc, anonymous function that will be called back by getXMLAnswer.
I prefer/use/recommend (and is better practice) to use the 1st technique.
One gets a named function which is easier to identify.
One uses the variable where it is defined - equivalent of only using local vs. global functions.
In contrast, when using binding what becomes the built-in variable this is defined not where it is used (so not in function setNumber), but where it is called.
In this example this might not be a problem, but just imagine how this would be implemented in a file with hundreds, or thousands of lines.
Finally one does not use variable this, which is the equivalent of using global variables, one never knows what it exactly means, as what it means is defined by how the function is called, it is prone to bugs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-01-2023 04:10 AM
That is a bit misleading as the function is not implemented everywhere (Core UI vs. Portal vs. Next) in the 3 parameter form.
But that is not a problem, you can "transmit" variables to the callback function using the closure "technique":
ga.getXMLAnswer(setNumber('output_2'));
function setNumber (field_name) {
return function callback (answer) {
g_form.setValue(field_name, answer);
};
}
Here getXMLAnswer will actually call ("inner"/returned) function callback, function that will have in its execution context variable field_name.
The same could be achieved using function binding too:
ga.getXMLAnswer(setNumber.bind({ field_name: 'output_2' }));
function setNumber (answer) {
g_form.setValue(this.field_name, answer);
}
When using the 1st technique one returns a function that will be called back by getXMLAnswer, when using the 2nd technique one defines/builds a new ad-hoc, anonymous function that will be called back by getXMLAnswer.
I prefer/use/recommend (and is better practice) to use the 1st technique.
One gets a named function which is easier to identify.
One uses the variable where it is defined - equivalent of only using local vs. global functions.
In contrast, when using binding what becomes the built-in variable this is defined not where it is used (so not in function setNumber), but where it is called.
In this example this might not be a problem, but just imagine how this would be implemented in a file with hundreds, or thousands of lines.
Finally one does not use variable this, which is the equivalent of using global variables, one never knows what it exactly means, as what it means is defined by how the function is called, it is prone to bugs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-01-2023 06:51 AM
Thanks for the very detailed answer! Seems like "bit misleading" is quite the understatement here :--))
I tested the 1st technique and it works exactly as it should, so that solves my problem.
p.s. if anyone from ServiceNow sees this, you should consider clarifying this since it's the same both in developer.servicenow and docs.servicenow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-01-2023 06:55 AM
You're welcome and I'm glad it helped 🙂
Also marking the correct answer is much appreciated.