Make loading icon appear only after 2 seconds
The ajaxStart() handler is only called if there are no other ajax requests currently in progress, so if there is already something in progress, the handler will never be fired.

Th ajaxStop() handler will only be called when a request completed and there are no other outstanding requests. So, theoretically, if you have ajax requests being fired every second, the loading icon could remain on your screen in perpetuity.  If you are looking at building a heavily ajax-driven UI, it might not be too wise to rely on the global ajax functionality for this reason, as you have to then concern yourself with interaction of different ajax requests and how they may impact the user experience.

From a UX standpoint, I would find it odd that you only want to display the loading icon until after 2 seconds have passed.  This seems like a really long time to wait to give the user some feedback that something is happening in response to some action they have taken.

There is no reason to have your global loadingIconOn variable at all. It would be preferable instead to work with jQuery queue functionality to give explicit control over how the animations are sequenced.

For example:

$(document).on({
    ajaxStart: function () {
        $('body').delay(2000, 'loadingIcon').queue('loadingIcon', function() {    
            $(this).addClass('loading').dequeue();
        });
    },
    ajaxStop: function () {
        $('body').clearQueue('loadingIcon').removeClass('loading');
    }
});


This also gives the advantage of having the function to delay then add the class specifically "scoped" to only be relevant to the body element as well as the opportunity to set up a specific queue (loadingIcon in this example), which deals only with this specific functionality.

Note that you don't need to use a custom queue like loadingicon. You could simplify this down by using the default fx queue, which would look like:

$(document).on({
    ajaxStart: function () {
        $('body').delay(2000).queue(function() {    
            $(this).addClass('loading').dequeue();
        });
    },
    ajaxStop: function () {
        $('body').clearQueue().removeClass('loading');
    }
});


But, I find it best practice to keep animations related to a certain set of functionality within their own queues so as to minimize potential conflicts with effects you might add in the future. Like say you added some functionality in the future to change some of other property/class on &lt;body&gt;, if the effects were in their own queue, they could be applied to the element simultaneously with the icon loading effect without causing undesirable interactions (obviously other than if they impact the same CSS properties in the loading class).