$A.util.removeClass happens seconds after execution

Lightning has some sort of digest cycle analogous to what you see in Angular and other front-end frameworks. When you make changes that affect the UI, they are not evaluated instantly but rather as part of the framework lifecycle.

As far as I know, when you fire an event it happens asynchronously. That means the current cycle continues executing and completes, and the async event doesn't evaluate in the UI until another lifecycle. Have you tried also logging the time during the steps of the dataChanged function to see the real sequence?

What's probably (approximately) happening is:

  • You fire the startWaiting event which is async
  • Your helper function updates the table
  • Your helper function sets the table data
  • The function finishes executing
  • The 1st framework lifecycle now reaches the stage where it re-renders the UI
  • The UI blocks while processing the re-render of the table
  • The re-render finishes and so does the 1st lifecycle
  • Now there is a startWaiting event to handle and the 2nd lifecycle starts
  • The $A.util.removeClass function sets the class parameter of the component
  • The 2nd lifecycle now re-renders

It sounds like what you really need is to make the spinner visible before re-rendering the table can block the UI. So I would flip this around. Fire the $A.util.removeClass immediately, not through an event. Then fire an event which completes the table update. If I'm right about this, the 1st lifecycle will complete quickly and show the spinner, while the table update will run in a 2nd lifecycle.

EDIT:


It is possible to break out of the Lifecycle as stated here

dataChanged: function(cmp, evt, helper) {
    $A.util.removeClass(cmp.find("spinner"), 'slds-hide');

    window.setTimeout(
        $A.getCallback(function() {
            var table = cmp.get("v.data");
            helper.updateTable(table, cmp);
            cmp.set("v.data", table);

            $A.util.addClass(cmp.find("spinner"), 'slds-hide');
        }), 0
    );
},