Progress Bar with Deferred process

Mar 4, 2015 at 2:23 PM
Hello all,

I was somehow thinking that by using a deferred process for using GetListItems operation, a progress indicator could be implemented. I saw the promises article:

http://sympmarc.com/2013/05/01/comparing-spservices-2013-01-calls-with-async-vs-promises-methods/

It looked like it waited for three different lists to be filled, and then it displayed them. Somehow, I was thinking that a progress bar could be implemented. I know that it's fairly easy to get a record count. Would it be possible to detect how much of the data has been retrieved in an array, and show the progress of the array being filled?

I know a few have tried to find a way to have a progress indicator for the queries, but they seemed to be on updates, and not just queries. Please let me know your thoughts.

Thank You

Once the array has been filled, the data could be displayed in the
Coordinator
Mar 5, 2015 at 12:28 PM
I'm guessing you're trying to do this in IE? Displaying progress in IE has always been tricky.

In this case, how would you know how far you've gotten if you haven't retrieved all of the data yet?

M.
Mar 5, 2015 at 12:48 PM
Edited Mar 5, 2015 at 12:48 PM
Hmmm. I guess that may be where I misunderstand deferred processes. Is it possible to just count up as the GetListItems is being filled in? I'm not sure as I haven't looked at how SPServices gets the data from the SP List(s). Would that take some looking into the functions that Micro$oft provides to access the data? I guess that's where I want to know your expertise, as to how is the list built up. Is there a quick way to explain that?

Thank You
Coordinator
Mar 5, 2015 at 2:11 PM
Any significant delay will be in the call to the server. The manipulation of the data on the client side usually goes by so fast that a progress indicator is pointless.

It all depends on the specifics of what you are doing.

M.
Mar 5, 2015 at 2:24 PM
Edited Mar 5, 2015 at 2:25 PM
All,

I have had to come up with a way to let users know that data is loading. It really only takes 5 seconds but they had to have it! My environment is a little different, but I use several deferrred processes in an array. I have to wait for all the data to be returned and then rendered on the screen. What I did that works for us was to use the SP.UI.Notify object to just tell them to wait. So my document ready starts like this:

    ExecuteOrDelayUntilScriptLoaded(function () { ExecuteOrDelayUntilScriptLoaded(function () { waitmsg = SP.UI.Notify.addNotification("Getting Data...Please Wait.", true); }, 'core.js') }, 'sp.js'); 
    
This may not be typical, but sometimes for us, the core.js file is not loaded as fast so I use this method to ensure that it works.

This creates the notification attached to the waitmsg variable. Then my promises array is setup and executed. I use the $when option of jQuery promises to basically wait for all the deferreds to complete. Then from there, I execute the code to modify the form/page with the returned data. Then I close the message.
var def = GetData();
    $.when.apply(null, def).done(function () {
        TabsLoaded();
    });
The GetData function just builds the array of deffereds so this waits for all of them to complete and then runs TabsLoaded. This calls a series of actions that massage and update the form. The last part of this I then call:
SP.UI.Notify.removeNotification(waitmsg);
And this hides the message. There are ways that you can manipulate the SP.UI.Notify with html and css, but this worked for us.

I hope that helps!

Dan
Mar 12, 2015 at 6:44 PM
Hello Dan,

Sorry it took me so long to get back to you. Your solution looked pretty good, except I'm using SharePoint 2007 for a bit longer. From what I've researched, it looks like SharePoint 2007 will not function with SP.UI.Notify.

Thanks for the potential plan, but do you know of any other options? I think I'm getting the idea that the user's computer is stuck waiting for the server to complete its operation, and the server is not that kind. So the web browser just sits there waiting until it can use the SPService's, completefunc commands that are there. That's very disappointing, but I guess what are you going to do? I thought somehow you could execute code that displays a simple spinning graphic or something before the query even goes, but alas, I may be out of luck.

Thank you for your input,

Matt
Coordinator
Mar 12, 2015 at 7:00 PM
Matt:

If you're still using completefunc, then you're not using asynchronous calls with promises. That will lock up the user's browser while waiting for the request. See: http://api.jquery.com/category/deferred-object/

M.
Mar 13, 2015 at 3:19 AM
Hello Marc,

Thanks. Yes I knew I was somewhat daft, and I'm trying to learn how to use the deferred asynchronicity available. So, perhaps that's a lot of my problem, you think? No, not that I'm too stupid to learn deferred functioning, that's obvious, but that I wouldn't have the lock ups if I figured out how to not do async: false setting. I'm trying to learn.

Thank You,

Matt
Coordinator
Mar 13, 2015 at 2:34 PM
Matt:

Check out this post:
http://sympmarc.com/2013/05/01/comparing-spservices-2013-01-calls-with-async-vs-promises-methods/
It may help you to see what you'll need to do to switch from synchronous to asynchronous calls.

M.
Mar 16, 2015 at 1:51 PM
Hello Marc,

I have seen the site, as posted at the beginning of this discussion, but it looked like it only handled three different processes that were deferred all in the same GetListItems. Once the three list item queries had been finished, it would then operate the final process to deal with the returned list(s). When I saw it, that's what got me thinking that I could somehow use the deferred processes to get a decent progress bar going, and I posted this discussion.

I appreciate all your help. It has been very informative and helpful. I know I'm a little too slow to get the understanding of how the deferred processes work, ... perhaps. I'm somewhat guessing that now I just need to perform my query and do it in an async manner such as this:
var tbody = "<tr><td >Returned Data</td></tr>"; 

 returnedItemList = $().SPServices({ 
    operation : "GetListItems", 
    listName : listame, 
    CAMLQuery : camlQuery, 
    CAMLViewFields : camlViewFields, 
  }); 
place in some code to trigger a graphic or a notice to the user, then use this to be triggered once the server responds:
$.when.apply($, returnedItemList).done(function () { 
    // List header 
    $(returnedLitItem.responseXML).SPFilterNode("z:row").each(function () { 
        tbody += "<tr><td >" + $(this) + "</td></tr>"; 
    }); 

At least that's my understanding of what to do. Please. Please. Please. Correct me if I'm mistaken. I haven't tried it yet, but I've been busy with other code.

Thank You,

Matt
Coordinator
Mar 16, 2015 at 3:29 PM
Matt:

Your code ablove is close, but this should be closer. The main benefit of making the call asynchronously is that you won't tie up the browser while it's going on.

As I mentioned above, the main "expense" in this isn't the processing of the items on the client side (unless you're requesting a high volume of data), but the call itself.
 var returnedItemList = $().SPServices({ 
    operation : "GetListItems", 
    listName : listname, 
    CAMLQuery : camlQuery, 
    CAMLViewFields : camlViewFields
  }); 

  returnedItemList.done(function () { 
    // List header 
    $(returnedItemList.responseXML).SPFilterNode("z:row").each(function () { 
        tbody += "<tr><td >" + $(this).attr("Title") + "</td></tr>"; 
    }); 
  }
M.