GlideRecord Script

crowe1288greg
Tera Contributor

My script looks good, but the results I'm receiving are not what I'm expecting. Here's the script:

var startTime = 0;
var endTime = 0;
var grMetric = new GlideRecord('incident_metric');
grMetric.addEncodedQuery('inc_number=INC0007001^mi_definition=35f2b283c0a808ae000b7132cd0a4f55');
grMetric.query();
	while (grMetric.next()){
		if(grMetric.mi_value == ("Resolved")){
			startTime = grMetric.mi_start;
			gs.print("Start Time: " + startTime);
		}else if(grMetric.mi_value == "Closed"){
			endTime = grMetric.mi_start;
			gs.print("End Time: " + endTime);
		}
	}
	gs.print(" ");
	gs.print("Start Time: " + startTime);
	gs.print("End Time: " + endTime);

 

The attached file shows the results. How is the variable 'startTime' being overwritten? Any suggestions.

2 ACCEPTED SOLUTIONS

Nick Parsons
Mega Sage

Your endTime (and startTime) are references, so they change on the next iteration of your loop when ServiceNow repopulates the property grMetric.mi_start to the value from next record. Can you try adding toString() to the end of your property access when storing the values? eg:

 

 

endTime = grMetric.mi_start.toString();

 

 

 Also, for debugging, it may help to differentiate the log text in your loop vs the logs outside of your loop so it's clear what's printing what (gs.print doesn't always log in the order it's used). 

View solution in original post

It's to do with how ServiceNow reuses the object references each time .next() is called. Internally, when you call .next() it updates the GlideElement's value (but reuses the same GlideElement object reference), and since endTime stores just a reference to the GlideElement, it changes too.

Example below on how it works (see code comments for mode details):

// .next() gets called the first time, this populates your GlideRecord object with the values from the database for the first row
var grMetric = { // <-- GlideRecord instance
  mi_start: { // <-- GlideElement instance
    _value: "XYZ", // value for first row
    toString: function() {return this._value;} // implicitly called when you use `gs.print`/`gs.log` on the `mi_start` object.
  }
  // ... other fields ...
};

var endTime = grMetric.mi_start; // `endTime` is a reference that points to the mi_start GlideElement object in memory
// Next iteration occurs, `.next()` is called:
// - Here, when `.next()` is called, the existing GlideRecord/GlideElement objects in memory are updated, new ones are NOT created, so the existing objects' values are changed
grMetric.mi_start._value = "ABC"; // <-- Internally, ServiceNow updates the GlideElements value (something like this), but the object reference remains the same

gs.info(endTime); // this would now print "ABC", not "XYZ" since `endTime` just stores a reference to the GlideElement in memory, which `.next()` modifies.


 

View solution in original post

4 REPLIES 4

crowe1288greg
Tera Contributor

I made a slight mistake. The variable 'endTime' is the variable that is being overwritten. How?

Nick Parsons
Mega Sage

Your endTime (and startTime) are references, so they change on the next iteration of your loop when ServiceNow repopulates the property grMetric.mi_start to the value from next record. Can you try adding toString() to the end of your property access when storing the values? eg:

 

 

endTime = grMetric.mi_start.toString();

 

 

 Also, for debugging, it may help to differentiate the log text in your loop vs the logs outside of your loop so it's clear what's printing what (gs.print doesn't always log in the order it's used). 

Thanks Nick. That worked!!

 

Can you help me to understand how the variable was being overwritten before the script change.

It's to do with how ServiceNow reuses the object references each time .next() is called. Internally, when you call .next() it updates the GlideElement's value (but reuses the same GlideElement object reference), and since endTime stores just a reference to the GlideElement, it changes too.

Example below on how it works (see code comments for mode details):

// .next() gets called the first time, this populates your GlideRecord object with the values from the database for the first row
var grMetric = { // <-- GlideRecord instance
  mi_start: { // <-- GlideElement instance
    _value: "XYZ", // value for first row
    toString: function() {return this._value;} // implicitly called when you use `gs.print`/`gs.log` on the `mi_start` object.
  }
  // ... other fields ...
};

var endTime = grMetric.mi_start; // `endTime` is a reference that points to the mi_start GlideElement object in memory
// Next iteration occurs, `.next()` is called:
// - Here, when `.next()` is called, the existing GlideRecord/GlideElement objects in memory are updated, new ones are NOT created, so the existing objects' values are changed
grMetric.mi_start._value = "ABC"; // <-- Internally, ServiceNow updates the GlideElements value (something like this), but the object reference remains the same

gs.info(endTime); // this would now print "ABC", not "XYZ" since `endTime` just stores a reference to the GlideElement in memory, which `.next()` modifies.