Service Portal widget $interval displays inconsistent results during refresh

heathers_
Kilo Sage

I have a widget that needs to refresh every one minute. I've got it working when executing the widget directly, however the client $interval alert does not match the server side data during it's refresh.

Client Script

api.controller=function($interval) {
  /* widget controller */
  var c = this;
	c.getData = function()
	{
	
	
	c.out = "";
	
	for(var i in c.data.metric){
		c.m_name =  c.data.metric[i].Name;
		
		c.out = c.data.metric[i].Value;
			
	alert( c.data.sample)
	c.random_out = c.data.sample;

	}		 
	 		};

	
		c.getData();
	$interval(function() {
		
         c.getData();
		  c.server.update();
		}, 60000);	
						
}


Server Script

(function() {
  /* populate the 'data' object */
  /* e.g., data.table = $sp.getValue('table'); */
var metric_result_1 = []; 
try {

   
     // Execute Synchronously: Run in foreground. Code snippet has access to outputs.
     var result = sn_fd.FlowAPI.getRunner().subflow('sn_amzn_conect_spk.aws_metric_output').inForeground().run();
     var outputs = result.getOutputs();

     var r_num = outputs['r_num']; // String
     metric_result_1 = outputs['metric_result_1']; // Array.Object
   data.metric = metric_result_1;  
	
    
 } catch (ex) {
     var message = ex.getMessage();
     gs.error(message);
 }
	
	data.sample = r_num;
	
	gs.addErrorMessage((r_num))

//var out = metric_result_1.toString();
//gs.addInfoMessage(JSON.stringify(out))

})();

 


Server side result after refresh:

heathers__0-1757458578848.png

 


Client side result after refresh:

heathers__1-1757458714401.png

 

1 ACCEPTED SOLUTION

kaushal_snow
Mega Sage

Hi @heathers_ ,

 

To ensure consistency, it's advisable to use c.server.get() instead of c.server.update() within your $interval function. This approach fetches fresh data from the server without sending the entire client-side data object, thereby reducing potential conflicts and ensuring the widget displays the most up to date information.

 

api.controller = function($interval) {
  var c = this;

  // Function to fetch fresh data
  function refreshData() {
    c.server.get().then(function() {
      // After successful fetch, update your UI outputs
      c.out = c.data.metric.map(m => m.Value).join(', ');
      c.random_out = c.data.sample;
    });
  }

  // Initial data fetch
  refreshData();

  // Set up periodic refresh every 60 seconds
  $interval(refreshData, 60000);
};

 

If you found my response helpful, please mark it as ‘Accept as Solution’ and ‘Helpful’. This helps other community members find the right answer more easily and supports the community.

 

Thanks and Regards,
Kaushal Kumar Jha - ServiceNow Consultant - Lets connect on Linkedin: https://www.linkedin.com/in/kaushalkrjha/

View solution in original post

3 REPLIES 3

SANDEEP DUTTA
Tera Patron
Tera Patron

Hi @heathers_ ,

The Server Script looks good to me but i feel the issue is with Client Script !!

You are calling both c.getData() and c.server.update() inside the $interval but c.getData() immediately reads from c.data which won't be updated synchronously before you read it.

 

Try the below code for your cleint script: 

api.controller = function($interval) {
  var c = this;

  c.getData = function() {
    return c.server.update().then(function(response) {
      c.data = response.data;

      c.out = "";

      for (var i in c.data.metric) {
        c.m_name = c.data.metric[i].Name;
        c.out = c.data.metric[i].Value;
      }

      c.random_out = c.data.sample;

      alert(c.data.sample); // place alert here to show latest data
    });
  };

  // Initial load
  c.getData();

  // Refresh every 60 seconds
  var refreshInterval = $interval(function() {
    c.getData(); // this will fetch latest server data and update c.data
  }, 60000);

  // Cancel interval on destroy
  c.$onDestroy = function() {
    $interval.cancel(refreshInterval);
  };
};

 

 

 

Thanks,
Sandeep Dutta

Please mark the answer correct & Helpful, if i could help you.

kaushal_snow
Mega Sage

Hi @heathers_ ,

 

To ensure consistency, it's advisable to use c.server.get() instead of c.server.update() within your $interval function. This approach fetches fresh data from the server without sending the entire client-side data object, thereby reducing potential conflicts and ensuring the widget displays the most up to date information.

 

api.controller = function($interval) {
  var c = this;

  // Function to fetch fresh data
  function refreshData() {
    c.server.get().then(function() {
      // After successful fetch, update your UI outputs
      c.out = c.data.metric.map(m => m.Value).join(', ');
      c.random_out = c.data.sample;
    });
  }

  // Initial data fetch
  refreshData();

  // Set up periodic refresh every 60 seconds
  $interval(refreshData, 60000);
};

 

If you found my response helpful, please mark it as ‘Accept as Solution’ and ‘Helpful’. This helps other community members find the right answer more easily and supports the community.

 

Thanks and Regards,
Kaushal Kumar Jha - ServiceNow Consultant - Lets connect on Linkedin: https://www.linkedin.com/in/kaushalkrjha/

Perfect! I had to use c.server.update() because .get() was not running the server script during refresh.