Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I want to use CSOM but waiting around 2 or 3 seconds after page load before I can even do my first query is crazy! See below. Using jQuery dom ready shows a reasonable ready time, but SP.ClientContext isn't defined yet. Using ExecuteOrDelayUntilScriptLoaded makes sure SP.ClientContext will be defined, but it takes too long. In Chrome it can be around 1 second or not fire at all, in IE it's 500ms, still not really good enough. Is there ANYTHING I can do to speed this up??

Generally I want to perform Ajax requests before dom is ready, then in the Ajax callback, place a dom ready listener if I want to modify the dom.

//console.time implementation for IE
if(window.console&&typeof window.console.time=="undefined"){console.time=function(e,t){if(!e){return}var n=(new Date).getTime();if(!console.timeCounters){console.timeCounters={}}var r="KEY"+e.toString();if(!t&&console.timeCounters[r]){return}console.timeCounters[r]=n};console.timeEnd=function(e){var t=(new Date).getTime();if(!console.timeCounters){return}var n="KEY"+e.toString();var r=console.timeCounters[n];if(r){var i=t-r;var s=e+": "+i+"ms";console.info(s);delete console.timeCounters[n]}return i}} 

console.time("SP");
ExecuteOrDelayUntilScriptLoaded(function(){
    console.timeEnd("SP");
    console.log(SP.ClientContext);  
}, "sp.js");

console.time("jQuery");
$(function() {
    console.timeEnd("jQuery");
    console.log(SP.ClientContext);      
});

Output:

jQuery: 67ms
undefined

SP: 2106ms
function()
share|improve this question

4 Answers 4

To do this you would need to have JQuery and other required libraries hard coded into the master page or layout page, this is the only way to ensure they are loaded before time, this is because if you use Scripts On Demand it probably won't finish loading until after the DOM is read, inline will be run and executed as soon as it is found, so put it in the head to make sure it is ready before the body is read.

If you are relying on page variables you will have to wait, there is no getting around that.

I like my jquery calls to be a little neater than most examples so excuse me for the slightly unorthodox approach.

If you want to garentuee your call is made as soon as it is read you need to immediately invoke the call, the sure way of doing this is a shorthand expression.

function callback() {};

(function() {

    var params = {
            q: "myQuery",
            p: "foo"
    };

    $.getJSON(requestAddress + "?",
        params,
        function (data) {
            if (typeof data === "undefined") {
                callback.call(this, false);
            } else {
                if (data === true) {
                    callback.call(this, true);
                }
                else {
                    callback.call(this, data);
                }
            }
        }
    );
})();

This is the fastest combination of tactics I can come up with to execute an ajax call asap.

1) Put in manual links to the JavaScript files that are required for that page layout

2) Execute your code in a predefined manner, and make sure it is self executing as a chunk, not being read as one line. For some reason when it executes JavaScript parsers perform much better.

3) Force internal libraries that you need NOW by using LoadSodByKey(key, func); the func will be run after the script has been loaded, and is exactly where your code will run the fastest.

As a side not you aren't understanding what ExecuteOrDelayUntilScriptLoaded is doing, and if notifyScriptLoadedAndExecuteWaitingJobs isn't being called, it will simply wait until nothing is being processed. Also if there is an error it won't execute the function either.

It is more a safety practice than anything else on Microsofts behalf, if you want this functionality then use it in a prehandled way registering with SOD and then loading from SOD with LoadSodByKey(key, func);

A further altenative is to use ScriptLink.RegisterDelayedExecutionScript this registers it into the queue and it will get processed.

In short ExecuteOrDelayUntilScriptLoaded has a queue and also won't run code with errors in. Use LoadSodByKey for custom scripts if you need to, but if you need it faster and you are using 2010 (Don't do this in 2013 stick with SOD) then hardcode the script link in.

Another note is you can register dependencies with the SOD so you can chain load required scripts. RegisterSod(Script, Dependency);

share|improve this answer
    
If I hard code the required files in, how to I prevent SharePoint then lazy loading them again a few seconds later? –  Fergal Mar 13 '13 at 22:48
1  
run this command: (the key is what is in the register SOD) NotifyScriptLoadedAndExecuteWaitingJobs("registerdJSKey.js"); –  Hugh Wood Mar 14 '13 at 10:34
    
Didn't work I'm afraid. <script src="/_layouts/sp.js"></script> then NotifyScriptLoadedAndExecuteWaitingJobs("sp.js"); but I can see that sp.js?rev=enHIfHdAu7IvZTmLeGCCbA%3D%3D is still downloading with Firebug. –  Fergal Mar 17 '13 at 14:57
    
your code to wait is running in a executeOrDelayUntilScriptLoaded for that to work right? –  Hugh Wood Mar 19 '13 at 14:48

Sorry about my previous post.

Okay so your problem is that ECMAScript doesn't run until after _spBodyOnLoadWrapper() function runs and that function behaves inconsistantly in Firefox and Chrome in the standard SharePoint method. If you look in your masterpage it is in the body tag as onLoad="_spBodyOnLoadWrapper()".

Fix: Remove the body onload and put in in a script funtion in the head. I have jQuery on my page so I have it load in the $(document).ready(function(){ });. Here is what it looks like.

$(document).ready(function(){ 
 //Fixes Chrome Scrolling problem and load of ECMAScript 
 if (typeof(_spBodyOnLoadWrapper) !== 'undefined'){
     _spBodyOnLoadWrapper(); 
 }; });
share|improve this answer
    
It fixes Chromes behavior but still the ExecuteOrDelayUntilScriptLoaded method takes too long in FF and Chrome –  Fergal Jan 29 '13 at 11:08
    
I have noticed that the time for ExecuteOrDelayUntilScriptLoaded is longer when the user first accesses the site when they don't have an active session. After the user has an active session it runs faster. Also remember that SharePoint is building a lot after your site is actually rendered (i.e. Ribbon Bar, Permissions), and those items can't be built until after the site is rendered. –  Daniel the Nerd Jan 30 '13 at 18:05
    
Always check types with === or !== this will prevent unexpected errors. If you are unsure if your code is correct check with a js linting program, a good on is available as a plugin for notepad++ –  Hugh Wood Feb 1 '13 at 17:02
console.time("SP");
SP.SOD.executeOrDelayUntilScriptLoaded(function() { 
    console.timeEnd("SP");
    console.log(SP.ClientContext);
}, "sp.js");

This seems to work consistently here. Note that the function is called thought SP.SOD, I looked for a "vs" in google and found this handy explanation:

SP.SOD.executeOrDelayUntilScriptLoaded(func, scriptName) schedules an asynchronous callback function (func) which will be called when the script has signaled finished loading. Signaled finished loading means that the script has called notifyScriptLoadedAndExecuteWaitingJobs(scriptName). All SharePoint built-in scripts will call notifyScriptLoadedAndExecuteWaitingJobs when they have finished loading. ExcuteOrDelayUntilScriptLoaded does not trigger loading an on demand script (SOD)!

So you might been having trouble because if you want the wonderful extra 1MB of scripts to use the CSOM you need to use a slightly modified version of the same method, simple isn't it?

Chrome console:

SP: 346.000ms
function (a){ULSdih:;SP.ClientContext.initializeBase(this,[SP.ScriptUtility.isNullOrUndefined(a)?SP.PageContextInfo.get_webServerRelativeUrl():a])} 

IE console:

SP: 463ms 
LOG: function(a){ULSdih:;SP.ClientContext.initializeBase(this,[SP.ScriptUtility.isNullOrUndefined(a)?SP.PageContextInfo.get_webServerRelativeUrl():a])} 
share|improve this answer
    
It's not very clear what you mean by: "ExcuteOrDelayUntilScriptLoaded does not trigger loading an on demand script (SOD)!". Can you elaborate? –  iOnline247 Jan 28 '13 at 20:21
2  
I didn't write it, but I think the meaning is clear enough, if you have a SOD it might not trigger with ExcuteOrDelayUntilScriptLoaded, because it does not propagate the notifyScriptLoadedAndExecuteWaitingJobs function, but SP.SOD.executeOrDelayUntilScriptLoaded does. –  F.Aquino Jan 28 '13 at 20:57
    
Thanks for the clarity because it didn't make sense before. –  iOnline247 Jan 29 '13 at 16:11

You haven't explained your script tag references. Do you explicitly have a reference to sp.js like you do for jQuery?

The way the question is written, you are comparing apples to oranges. The jQuery script has already loaded, however the sp.js hasn't. Using the ExecuteOrDelayUntilScriptLoaded method has to go to the server, download the script and then initialize it. If you don't have an explicit <script> tag referencing sp.js, your code's performance will always suffer.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.