5

I have had a big problem with race conditions in ActionFunctions corrupting my viewstate.

When I call an AF to update one thing, and then click a button to do another, if the second finishes first, and then the actionfunction completes, ViewState gets reset to the result of the actionfunction.

This is a pretty straightforward symptom of ViewState. It is also a problem when a component calls one function, and then the page calls another, since both modify the entire viewstate.

I attempted to solve this by creating a window level function runAf(actionfunction), and in the oncomplete of every actionfunction call afComplete();

function afComplete(event){

    if (window.AF_Queue.length == 0) {
        window.RunningAF = false;
     } else {
        var fn = window.AF_Queue.shift();
        fn();
    }
    return false;
}

function runAf(af) {
    if (!window.RunningAF) {
       window.RunningAF = true;
       af();

    } else {
        window.AF_Queue.push(af);
    }
}

Both the page and controller use this to run their action functions. Unfortunately, nothing happens, and the actionfunctions fail to execute entirely.

I am at wits end on this, and don't want to re-write something that works perfectly, just because clicking buttons too fast causes it to break.

I considered moving to Remote Functions, but I don't trust that they will work used this way based on my experience with actionfunctions.

Any insight?

  • FWIW - you (or others) might want to check out Bob Buzzard's book (under his real name, Keir Bowden) - "Visualforce Development Cookbook", chapter 7 Javascript - section 'Avoiding Race Conditions' – cropredy Nov 27 '14 at 1:28
  • I am actually finding, if I set last_af = 'somestring' in the controller action, and reRender <script> window.last_af = '{!last_af'}'; </script>. window.last_af does not get changed. So it is definitely broken. – Alex H Nov 27 '14 at 20:45
3

One simple workaround could be that if an event fires or a button is clicked, you put a fullsize div z-index 9999999 on top of the entire page. This can prevent any ui elements from being clickable.

Now depending on how you rerender the page, either it will refresh entirely and the div is just gone, or you have to remove it manually, e.g. by a script inside the rerenderd markup.

Setting the transparency of the div and also adding a kind of spinner gif it even looks ok.

This may not solve all issues. Since you can suppress ui interactons after any events or other ui interactions, you still may get race conditions triggered by events after events - e. g. repetitive resizes or keystrokes may still cause a race condition.

I don't think that remote functions generally prevent race conditions. But they may complete way faster than action functions and simply that could reduce the chances to a sufficient degree.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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