Search code examples
settimeoutservicenowrootscopeangularjs-rootscope

ServiceNow: issue with recordWatch and $rootscope timing


Our team is developing an application in ServiceNow. We have a recordWatch on a widget that updates dynamically, but we also want to use rootscope to broadcast data to another widget and have something else update as well. The issue we're running into is a delay in the $rootscope and we're not sure how to mitigate it.

Our Server Script looks like this:

data.tasksCompleted = false;

    if (input && input.action === 'getTasks')
        getTasks(data.user_id);

    function getTasks(userId) {
        data.tasks = new sn_hr_core.hr_Task().getMyTasks(data.user_id);
        for (var i = data.tasks.length-1; i >= 0; i--) {
            var task = new sn_hr_sp.hr_TaskTicket().getTasks(data.tasks[i].sys_id, 'sn_hr_core_task');
            data.tasks[i].taskInfo = task;
            if(data.tasks[i].state == '3'){
                data.tasksCompleted=true;
            }
        }
    }

And our Client Script with the recordWatch looks like this:

spUtil.recordWatch($scope, 'sn_hr_core_task', '',function(event,data){
        spUtil.update($scope);
        setTimeout(function(){ 
            $rootScope.$broadcast('onboardingCompletedTasks', $scope.data.tasksCompleted);  
        }, 5000);   
    });

We had to use a setTimeout with a 5 second delay in order for the other widget to receive the tasksCompleted flag and update accordingly. Without the 5 second delay, the recordWatch works too fast and the other widget does not update at all. Is there a way to make these things smoother? Our current way works...but the user experience is terrible.

Any suggestions welcomed. Thanks!


Solution

  • The root problem here is that spUtil.update($scope); is async and the $broadcast will happen before the Server has loaded all Tasks.

    What you need to do is to send the $broadcast after your server logic is done.

    I would suggest you watch data.tasksCompleted on the client and put the broadcast in the callback:

     $scope.$watch(data.tasksCompleted, , function(value) {
        if (value)
        $rootScope.$broadcast('onboardingCompletedTasks', $scope.data.tasksCompleted);
      }); 
    

    This way, when data.tasksCompleted updates from the server to true the broadcast will be sent.