Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intercooler.ready calls stack handlers but don't allow them to be cleared #294

Open
esb opened this issue Oct 3, 2019 · 10 comments
Open

Comments

@esb
Copy link

esb commented Oct 3, 2019

In a previous issue, I'd raised the problem of running code after the Intercooler swap had completed. It was pointed out that I could use the Intercooler.ready function in the IC-Script header to kick off my cleanup code when everything had finished.

This is great, but now I've run into a bit of a problem because each call to Intercooler.ready pushes the ready function onto a global stack. In my particular situation, I'm using IC to respond to a user request which may or may not work. If it fails, I set an error response using IC-Script and Intercooler.ready, and if it succeeds, then I set a different response to indicate that it worked.

Now, if the user makes several attempts to use this function, the previous ready handlers are still active on subsequent attempts. So, if a failed attempt was made, then on a subsequent successful attempt, you get back both the failed attempt handler AND the successful attempt handler.

What would make this workable would be if there were a single shot handler capability, like the jQuery one function. I don't need the handler to be permanent, but there's no way to turn it off once installed.

@esb
Copy link
Author

esb commented Oct 3, 2019

A pretty trivial solution to this scenario is to add a new Intercooler.one function (or equivalent).

This simply replicates the current ready function, but creates a separate array of handlers which are automatically cleared once they have been called in the fireReadyStuff routine.

@baumann74
Copy link
Contributor

baumann74 commented Oct 3, 2019 via email

@scsmash3r
Copy link
Contributor

A pretty trivial solution to this scenario is to add a new Intercooler.one function (or equivalent).

This simply replicates the current ready function, but creates a separate array of handlers which are automatically cleared once they have been called in the fireReadyStuff routine.

Since Intercooler depends on jQuery, you can use jQuery.one([...]) inside Intercooler.ready() function. Is it suitable solution?

@esb
Copy link
Author

esb commented Oct 3, 2019

Not really. Every call to Intercooler.ready pushes the function onto the stack of ready handlers. Pushing multiple calls to jQuery.one doesn't really get around the problem.

@scsmash3r
Copy link
Contributor

Not really. Every call to Intercooler.ready pushes the function onto the stack of ready handlers. Pushing multiple calls to jQuery.one doesn't really get around the problem.

Hmm... Can you link a piece of logic of your code to be sure?
Maybe you want to use X-IC-Trigger instead? You could send back headers like this, i.e. (PHP example, some response, that came from backend):

// In case of failure
return $response->withHeader('X-IC-Trigger', '{"callableTrigger":["fail"]}');

// In case of success (or do some other stuff/sending another header)
return $response->withHeader('X-IC-Trigger', '{"callableTrigger":["success"]}');

And simply trigger jQuery.one() like so (JS part):

jQuery("body").one("callableTrigger", function(data) {
    if (data == 'fail') {
        Intercooler.ready(function(data) {
            //doSomething
        });
    }
});

@esb
Copy link
Author

esb commented Oct 4, 2019

I use IC-Script to set a ready handler with Intercooler.ready to kick off some post swap cleanup actions. The problem is that the ready handler, once invoked, never goes away and gets executed even when different ready handlers are installed. This is the problem with having multiple Intercooler actions on a single page.

Using a jQuery.one handler inside the ready handler does not help, since the handler gets executed on every new IC request.

IC-Trigger is of no help. It gets triggered at the beginning of processing, so there's no callback when the transition processing has completed. Unless you use Intercooler.ready, and you're back to the same problem.

I coded up my idea of a single-shot ready handler and it solves the problem neatly, without the need to have complex logic in some sort of global handler which tries to work out which handler has been executed or not.

@1cg
Copy link
Contributor

1cg commented Oct 4, 2019

@esb do you have a patch? I'd be fine adding an Intercooler.once() function to like up with the JQuery API.

@esb
Copy link
Author

esb commented Oct 4, 2019

Great! I'll code up a pull request over the weekend.

@1cg
Copy link
Contributor

1cg commented May 12, 2020

@esb ever get to making a patch?

@esb
Copy link
Author

esb commented May 12, 2020

@chg20 Sorry, work has got really busy and I haven't been able to find the time to write test cases for the patch. The patch is really simple, and it's been working in production for many months now.

This is the diff

27d26
<   var _onceHandlers = [];
763,770d761
<     $.each(_onceHandlers, function(i, handler) {
<       try {
<         handler(elt);
<       } catch (e) {
<         log(elt, formatError(e), "ERROR");
<       }
<     });
<     _onceHandlers = [];
2028,2030d2018
<     once: function(onceHandler) {
<       _onceHandlers.push(onceHandler);
<     },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants