http://qs1969.pair.com?node_id=1172386

stevieb has asked for the wisdom of the Perl Monks concerning the following question:

Right off the bat, I am positive this is a jQuery/Javascript issue, but before I ask questions on a forum that isn't Perlmonks, I'm hoping a Perl web monk could help.

I've got a Dancer2 application that works well. I have a couple code snips without any context, but know for fact that the following returns to the jQuery call either 0 or 1:

get '/get_aux/:aux' => sub { my $aux = params->{aux}; return _aux_state($aux); }; sub _aux_state { # maintains the auxillary state (on/off) my ($aux, $state) = @_; return $auxs->{$aux}{state} if ! defined $state; $auxs->{$aux}{state} = $state; return $state; }

Now, in my javascript, I *know* that I receive the proper information. On page load finish, I set up a button (which is a glorified checkbox). It's 'checked' value should be a call back to the Perl code. I've augmented and hacked the jquery code so I can see what's happening. In this code, I call aux_state() to set things up. LINE 1, depicted in comments, alerts undefined. However, while I'm in the aux_state() function itself making the call back to Perl (LINE 2), I get an alert with the expected result:

$(function(){ var state = aux_state('aux1'); alert(state); // LINE 1 $('#aux1').switchbutton({ checked: aux_state('aux1'), onChange: function(checked){ $.get(host +'/set_aux/aux1/'+ checked, function(state) +{ // ... }); } }); }); function aux_state(aux){ $.get(host +'/get_aux/' + aux, function(state){ alert(state); // LINE 2 return state; }); }

I'm totally missing something with jQuery me thinks. Can anyone point me in the right direction? This is my first real attempt at writing async jQuery code. If not, I will proceed to ask on SO.

I'm assuming my newbness in jquery is the issue here particularly with callbacks and returning things. If so, a pointer to a *good* doc would be handy. Even though I'm certain this isn't a Perl issue, I'd rather look at home before I go elsewhere (yep, I've searched online, but couldn't find anything conclusive perhaps because I don't know what to search for).

Thanks,

-stevieb

update: I'm currently reading this.

Replies are listed 'Best First'.
Re: jQuery issue with Dancer2
by Corion (Patriarch) on Sep 23, 2016 at 05:24 UTC

    This has nothing (nothing!) to do with Perl at all.

    If you eliminate the $.get call and replace it by something else that calls your callback, you will see exactly the same.

    Your aux_state function never returns a value, because it doesn't have a return statement:

    function aux_state(aux){ $.get(host +'/get_aux/' + aux, function(state){ alert(state); // LINE 2 return state; }); }

    The return statement you see is for the callback function that gets invoked asynchronously by jQuery. The aux_state function returns immediately and returns no value.

    To capture the return value of your $.get() call asynchronously in Javascript, you will have to pass in another callback to aux_state which then gets invoked once the value is available. This is what people name Callback Hell.

Re: jQuery issue with Dancer2 (return)
by tye (Sage) on Sep 23, 2016 at 05:39 UTC

    Your aux_state() function doesn't return any value. In case you didn't realize, in javascript, 'return' isn't implied like it is in Perl. If that is what you thought, then you also might be assuming that the return value from .get() is the same as the return value from your success function? But I didn't see any mention of a return value from .get() when reading the documentation that I found by searching for jQuery .get.

    If JavaScript didn't lack co-routines and so didn't force you into the fragmented code of call-back hell, then you could do something like:

    function aux_state(aux){ var returned; $.get(host +'/get_aux/' + aux, function(state){ alert(state); // LINE 2 returned = state; }); return returned; }

    And the nature of "call-back hell" infects all of the callers of your function so you probably just can't end up with something that would work for the code you wrote as:

    var state = aux_state(­'aux1');

    You likely have to have yet another call-back that would get the fetched state passed to it.

    - tye        

Re: jQuery issue with Dancer2
by Your Mother (Archbishop) on Sep 23, 2016 at 00:25 UTC

    I’m pretty handy with jQuery but it’s hard to see what’s going on or how to test what you’re doing so I’m sorry I have no help, just a rude question. :P

    I have had an arm’s length distaste for Dancer since its debut—not knowing it well enough to say while also not liking anything I do learn about it—but is that really how URLs are handled? With hard-wired, string concatenation? Is there nothing like Catalyst’s uri_for(), uri_for_action(), or uri_with()?

      I'm no Dancer expert and I only have limited experience with using it. But that was still long enough for me to experience ETOOMUCHMAGIC from Dancer. Since then I have repeatedly seen evidence of more of that. I also see Dancer/2 suffering more from "framework disease" than Mojo does. Framework disease is where there is much rejoicing about how you can build a whole functioning system with just 1 trivial line of code. This then leads to major spelunking required to detangle all of the magic that was hidden in order to make all of those things dance with such little specified. The spelunking need can come up any time you want to do something even a little different than the default way.

      But then, the many things I built didn't even use Mojo. They just used Plack.

      As for building URLs with concatenation, I've just come to expect such stupidity from all web frameworks. Before I had experience, I expected building URLs properly would be something built directly into JavaScript. Then I expected it to be someplace obvious in jQuery. Then I expected Mason to handle such things. But I almost never find tools for doing that in such places. And I have never found code written by others and using such tools that builds URLs other than by concatenation, and only rarely is any escaping done before concatenation.

      - tye        

      Thanks Your Mother, no rudeness spotted :)

      The Dancer part doesn't really matter, as I know that I'm receiving what I expect from the Perl Dancer part. It's how I'm handling the JS. In the get_aux() js call, when I alert() I get the expected result (from Perl). But in the creation of the button (the call that calls the get_aux() in the function above it in my OP), the alert() states undefined.

      I'm reading up on use of 'callbacks' et-al right now.

      What *is* rude, is me looking for JS help on Perlmonks ;)

        Oh, I love the occasional JS question, especially jQuery. I have said before, I really think it touches the same sweet spot Perl does in terseness + expressiveness. If you have runnable code somewhere (github gist?) I would probably play with it tomorrow.

Re: jQuery issue with Dancer2 (a problem summary)
by Anonymous Monk on Sep 23, 2016 at 00:46 UTC

    So what is the issue/problem?

    You need to summarize the question, like why is state empty  $.get(host +'/get_aux/' + aux, function(state){

    I suggest you study Mojolicious::Lite +and jQuery +AJAX + Mojo::Template both the perl and the javascript (and references), as headers (like content type) matter, and so does handling failure

      Thank you.

      I think I stated the problem clearly... that state is returned from the Perl Dancer2 call here: $.get(host +'/get_aux/' + aux, function(state){ as you said, but as soon as I leave that function (and get to its outer, surrounding called function), the return is undef. I'm sure it's just that I'm not explaining/understanding the JS language properly. In other words... FFS, it should be like Perl ;)

      I'll have a read-through of the docs you supplied.

      Cheers,

      -stevieb

        I think I stated the problem clearly....

        :) I didn't see any question marks or any sentence in the form of a question :D

        Consider this format

        Title: question here?
        question here again?
        setup
        data
        code
        diagnostics
        details 
        question here again?
        signature
        
Re: jQuery issue with Dancer2
by stevieb (Canon) on Sep 23, 2016 at 23:10 UTC

    Hey all, I admit that I was a bit under the influence when I posted this yesterday, and to those who may have been offended for it not being Perl related (rightfully so), I apologize. I normally am restrained in making such decisions, but I didn't.

    However, because I started this, I'd like it to be concluded. My team lead at work who's very experienced in JS gave me some pointers (I was having issues finding good resources online that put it in a way I easily understood. He explained the whole "callback hell", and in some ways, try to avoid it. Although he gave much better suggestions and pointers than the following, it's what I came up with that I understand to go forward with hacking jquery for the amount I'll need.

    I simply call the overarching function on page load, and let it naturally (well, as naturally as JS can be I suppose) handle the whole chain in order. Knowing how jquery/js passes things around, that made it a bit easier to understand.

    $(function(){ for(i = 1; i < 4; i++){ var aux = 'aux'+ i; aux_state(aux); } }); function aux_state(aux){ $.get(host +'/get_aux/' + aux, function(state){ $('#'+ aux).switchbutton({ checked: parseInt(state), onChange: function(checked){ $.get(host +'/set_aux/'+ aux +'/'+ checked, functi +on(data){ // do perl stuff }); } }); }); }

    Your Mother, because this is a hack job with web UI, my code is all over the map, as I'm just learning. You can find it here on my github. Because I was fudging, you actually have to install the thing (normal steps of installing apply with make), and install some prereqs:

    sudo apt-get install sqlite3 cpanm Dancer2; cpanm Dancer2::Plugin::Database

    Perhaps others (I haven't properly managed the dependencies while playing around). I then run the app with plackup -R lib,bin,public bin/app.pl, which runs it on port 5000.

    Anyways, eventually, it'll be a one-page interface to my Raspberry Pi based indoor grow environment automation control system.