- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 08-17-2021 10:59 PM
Applies to Quebec and Rome releases.
Yesterday I learned something surprising about Service Portal widgets. Maybe other know this already but after working with the Service Portal since its release I did not know this and have never encounted problems because of it. Until Quebec and Rome releases!
I am building a service portal application with multiple widgets that communicate via angular service. So when a button is clicked in one widget a message is sent and the other widgets act accordingly for example by showing or hiding information etc.
I started this on a Paris PDI before Quebec was released and everything was fine. Then because of other work I did not continue the work until my PDI was upgraded to Rome and now the problem appeared. Something that worked before now became extremely slow. One widget (one one out of 10) started to update the html very slowly. Somwtime it could take up to 1 minute before the view was updated.
After many hour of debugging, removing code etc to try to isolate what was causing the delay I finally found the answer in a stackoverflow question that mentioned $scope.$apply. I had never heard about that and never seen it used in any OOB Service Portal widgets (it is used in less than 10 OOB widgets).
The AngularJS documentation says that when updating $scope outside a digest you should use $scope.$apply.
So of course I immediately tried to add this simple line of code and voila the widget in question updated fast again. A simple solution that took many hours for me to discover.
Consider following code in the client controller part of a widget, this code subscribes to a service and wait for a specific message. When that message arrives it updates a variable in $scope in order to display it in the html with {{}} binding syntax:
$(document).ready(function () {
var removeListener = someService.addListener(function (action) {
if (action.action == 'doSomething') {
$scope.field = action.someData;
$scope.$apply();
}
});
});
Without the $scope.$apply() the update of html can take as long as one minute. With it is done immediately.
I have confirmed that Quebec introduced changes to the Service Portal that makes change necessary. I confirmed it by loading my application on a Paris PDI and ran the widget without the $scope.$apply() and it worked as expected with no delays. Then I upgraded the PDI to Quebec and made no changes to the widget but now it was extremely slow. Then I added the extra code and the widget worked correct again. Then just to re-confirm I upgraded the PDI to Rome and the same would happen in both cases with and without the new code.
So the question is now when to add this extra line of code. Well as mentioned the AngularJS documentation says whenever you modify $scope outside a digest. Hmm I am not sure when ServiceNow Service Portal widget client code runs in a digest. But the good news is that you will be told if the apply is NOT necessary. So I will add the code whenever I update something in $scope and test. If I need it then everything is fine but if the code is already running in a digest then an error message will appear in the console log stating that code is already running in digest. So I will then remove the line again.
And as mentioned this code is not widely used in OOB widgets which is why I never ran into this. I usually go checkout new widgets when a new release is available.
I hope this helps other developers from spending hours figuring out why a widget suddenly is slow in Quebec and Rome.