0

I am trying to create a javascript plugin that allows you to hook into the save operation. I want some logic wrapped around the logic though:

  1. Show a spinner
  2. Execute save hook-in
  3. Execute save logic
  4. Remove Spinner

here is an example of my code:

function save(){
    var settings = getSettings();

    showSpinner();

    // Hook-in call
    if(settings.onSave)
        settings.onSave();

    saveState();

    removeSpinner();
}

showSpinner() just hides save/cancel buttons and shows a spinner in its place.

hideSpinner() does the opposite.

saveState() saves the data from input fields to their data attributes.

settings.onSave() can be whatever code is passed in to the config by a user of the plugin.

When I run the process the spinner never shows up even though the hook-in I have defined takes ~1.5 seconds to return. If I pause the code in the debugger, the spinner does have a chance to show and it does disappear after the operation is complete.

What is the best approach to resolve this? I am not at all familiar with asynchronous design patterns within javascript. I know there is a single thread that the javascript can run on but I don't know why the save operation is getting in the way of showing the spinner.

Cœur
  • 37,241
  • 25
  • 195
  • 267
scottmgerstl
  • 765
  • 8
  • 18
  • possible duplicate of [How to display 'Loading' when making a 'synchronous' AJAX call in pure JavaScript?](http://stackoverflow.com/questions/8019078/how-to-display-loading-when-making-a-synchronous-ajax-call-in-pure-javascrip) – epascarello Jan 24 '13 at 16:10
  • 1
    It's actually kind of an exact duplicate, but IMHO, the answer lacks a demonstrable solution and is a bit disappointing. – FrankieTheKneeMan Jan 24 '13 at 16:15

1 Answers1

1

Your browser won't update the interface until Javascript gives back control to the browser, meaning you need to return from function before the browser will show the spinner. Use setTimeout to give control back to the browser briefly.

function save(){

    showSpinner();

    setTimeout(function(){
        var settings = getSettings();

        // Hook-in call
        if(settings.onSave)
            settings.onSave();

        saveState();

        removeSpinner();
    }, 0 );
} 
FrankieTheKneeMan
  • 6,645
  • 2
  • 26
  • 37
  • This works and thank you for the answer. However, and I understand why, the spinner .gif does not rotate. Is there a design pattern I can use to make the save call asyncronous even if it is not defined so by the user passing in the hook-in function? – scottmgerstl Jan 24 '13 at 16:18
  • Not really, no. In my experience, the browser itself should be multithreaded enough to spin a .gif while executing javascript. What exactly does your settings.onSave() do in this case? – FrankieTheKneeMan Jan 24 '13 at 16:22
  • Whatever the user defines. In my case, it makes a synchronous call to my web service to save some data to my database. The reason it is synchronous is because I want to run operations after the hook-in and I could never know ahead of time what a user, other than myself, would define as the hook-in function. – scottmgerstl Jan 24 '13 at 16:25
  • Problem is, if you hand over total control to a user (like letting them write a save function), then there's not much you can do about how they exercise that control. Javascript contains no way to force a redraw, and no reliable, functional way of modifying someone else's code. Oh, and it turns out I was wrong - you can't animate a gif while JS is executing. Why? I'm not sure. Seems silly. – FrankieTheKneeMan Jan 24 '13 at 16:35
  • I'm going to try one more thing that I found here [why-does-my-spinner-gif-stop-while-jquery-ajax-call-is-running](http://stackoverflow.com/questions/191413/why-does-my-spinner-gif-stop-while-jquery-ajax-call-is-running). I'll let you know if it helps. – scottmgerstl Jan 24 '13 at 16:41
  • It looks as though you are completely right. I will have to just leave it up to the implementer of the plugin to add the spinner functionality on their own. I'll just have expose the methods for them to be able to call from their save method if they desire too. – scottmgerstl Jan 24 '13 at 17:20