Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

My JavaScript waitForEvent() nightmares ....

Îåêßíçóå áðü ôï ìÝëïò anjelinio. Τελευταία δημοσίευση από το μέλος anjelinio στις 08-04-2009, 18:26. Υπάρχουν 2 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  06-04-2009, 18:27 49915

    My JavaScript waitForEvent() nightmares ....

    Κι άκου τώρα τί παθαίνει ο άνθρωπος αν μπλέξει με ... μπελάτες ...

    Υπάρχει μια σελιδούλα που λέτε, η οποία κάνει περιοδικά AJAX refresh calls στον εαυτό της, κάνοντας monitor το status μιας δουλειάς που τρέχει στο server.

    Αυτό το job στο server λοιπόν, που και πού δίνει πίσω warnings ( κατά τη διάρκεια της λειτουργίας του, όχι μόνο στο τέλος της ), κι όταν με το καλό τελειώσει, πρέπει τότε να εκτελεστεί κάτι άλλο, κι αυτό όμως ξεκινάει στο UI.

    Τα warnings λοιπόν, φαίνονταν στην αρχή με alert boxes. Μετά όμως, επειδή ο μπελάτης δε γούσταρε γκρί pop-ups που του χαλάγανε την αισθητική ( κι αν δεν πατήσεις και οκ μπλοκάρουν το browser ο οποίος περιμένει να πατήσεις το οκ ... οπότε πάνε τα ajax refreshes ... ), πετάγονταν σε ένα ψευτο-pop-up με ένα div-άκι όμορφούλι.

    Μια χαρά ως εδώ ... αλλα το div-άκι ήταν .. singleton ! Οπότε, μόλις του λες "δείξε αυτό", δείχνει ... αυτό, κι αν στα καπάκια του πείς "δείξε κάτι άλλο", τότε δείχνει κάτι άλλο.

    "Α ... δεν το θέλω αυτό ... " λέει ο κακός μπελάτης  ... " γιατί εξαφανίζεται προτού διαβάσω το μήνυμα λάθους και πατήσω το κίτρινο 'οκ' ... " ... και κλάμα εμείς, γιατί το ένα χαλάει τα refresh, το άλλο χαλάει ... τον πελάτη Big Smile

    Καίγοντας λίγο το μυαλό μου, σκέφτηκα το εξής. Αυτο που ήθελα στην πραγματικότητα, ήταν ένας τρόπος - σε Javascript - να μην εκτελείται μια κλήση μου, αν πρώτα δεν έχει γίνει κάτι άλλο. Κι αυτό, χωρίς να μπλοκάρω το browser, ώστε να τρέχουν και τυχόν άλλα scripts παράλληλα. ( ¨ενα while loop απο την άλλη, μπορεί επίσης να στείλει τη CPU σας στο ... 500% πολύ γρήγορα στον I.E. )

             . . .

    Άντε, λέω ... ένα while ( !myCondition ) setTimeout( callMeAgain ) είναι, τίποτα σπουδαίο.

    Και μετά τρώς τη συνειδητοποίηση. Το setTimeout παίρνει το script που είναι να τρέξει ως string. Εγώ όμως έχω παραμέτρους για την κλήση μου, οι οποίες δεν είναι σε global scope, δε μπορώ να κάνω eval ένα script με τα ονόματά τους μέσα !!! Κλάμμαααααα ..... Crying

    Οπότε; Τι κάνεις τώρα;

    Μετά απο λίγη σκέψη ακόμα λοιπόν, κατέληξα στο εξής όμορφο ...

    // I'm planning to store the "when" and the "callthis" functions here, under a unique key. 
    var _executeWhenMap =  { };
    
    /*
        Executes funcToExecute only after funcWhen returns true, otherwise
        it will wait for a few millis, and try again. 
    */
    function ExecuteWhen(funcToExecute, funcWhen) {
        /*  ok, what I want to do is this:
    
            If my when() function returns FALSE, I'm building a little struct with the
            when() and toExecute() functions, ans store it in the global executeWhenMap[] under a unique key.
            
            Then, I just setTimeout(...) executeWhenInternal, with the key as the argument ;)
        */
        if(funcWhen())
            funcToExecute();
        else {
            // create my little ExecuteInfo here ...  
            var executeInfo = { "When":funcWhen, "Do":funcToExecute };
            var myUniqueKey = (new Date()).getMilliseconds().toString();
            
            _executeWhenMap[myUniqueKey] = executeInfo;
            
            setTimeout("ExecuteWhenInternal('" + myUniqueKey + "');", 10);
        }
    }
    
    /*
        Queries the executionMapStack thingy for a given executionInfo key,
        and does the .. if(when()) do() else setTimeout(executeWhenInternal(myOriginalKey), 10 ) thing ... and God be with us ... 
    */
    function ExecuteWhenInternal(strExecuteInfoKey){
        // ok, na doume an exw eceuteInfo gia ayto to key edw ...
        var executeInfo = _executeWhenMap[strExecuteInfoKey];
        // exw ???
        if(null == executeInfo || "undefined" == typeof(executeInfo)) 
            throw "ExecutionInfo for Key: " + strExecuteInfoKey + " was not found in the execution map";
        else {
            var funcWhen = executeInfo.When;
            var funcToCall = executeInfo.Do;
            
            if(funcWhen()){
                funcToCall();
                _executeWhenMap[strExecuteInfoKey] = null;
            } else
                setTimeout("ExecuteWhenInternal('" + strExecuteInfoKey + "');", 10);
        }
    }
    Τι κάνει τώρα τούτο δώ ... στην πραγματικότητα, κάνει αυτό που δεν κάνει η  JavaScript απο μόνη της. Κάνει τη μέθοδο που θέλα να εκτελέσω, μαζί με τη μέθοδο η οποία ελέγχει αν μπορώ να την εκτελέσω ... global, και string-addressable.

    Υπάρχει δηλαδή ένα Dictionary στη μνήμη, το οποίο δέχεται entries βάσει ενός string key, τα οποία περιέχουν τις 2 μεθόδους, τη "when" μέθοδο ( μπορώ να εκτελέσω τον κώδικά μου τώρα; ), και τη μέθοδο που τελικά θέλω να εκτελεστεί ( αυτό είναι ο κώδικας που ήθελα να εκτελέσω απ'την αρχή ... ).

    Έτσι, μπορώ να κάνω setTimeout, και μέσα εκεί να βλέπω αν πρέπει να εκτελέσω ακόμα ή να περιμένω, και να πράξω πλέον τα απαραίτητα execute ή setTimeout στον εαυτό μου για αργότερα.

    Το δοκίμασα σε μια html σελίδα με 2 κουμπάκια. Το πρώτο κάνει ένα απλό alert('hello'). Το δεύτερο ανοίγει και κλείνει μια boolean μεταβλητή. Θέλω τα alert να εκτελεστούν, μόνο αν η boolean είναι "ανοιχτή". Αλλιώς, θα εκτελεστούν αν και όταν ανοίξει ποτέ αυτή η boolean !

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Untitled Page</title>
        <script type="text/javascript">
        
            var _continue = false;
            
            function CanIContinue() {
                return _continue;
            }
            
            window.status = !_continue;
            
        </script>
        <script type="text/javascript" src="ExecuteAfter.js" > </script>
    </head>
    <body>
        <input type="button" value="Start/End Blocking" onclick="_continue = !_continue; window.status = !_continue;" />
        <input type="button" value="Try alert('hello');" onclick="ExecuteWhen(function() { alert('Hello !!!');}, CanIContinue );" />
    </body>
    </html>
    Και ως δια μαγείας ... έπαιξε !!! Ανοίγω το "blocking", πατάω 2 - 3  κλικ στο "alert" κουμπί .. και δε γίνεται τίποτα. Μόλις κλείσω το "blocking" ... μαγικά εκτελούνται ΟΛΑ τα κλικ που είχα κάνει κλίκ πριν Smile

    Τώρα αν σκέφτεστε γιατί σας πρήζω με όλα αυτά τα JavaScript-ικά ( η ρήμα με τα Σανσκριτικά δεν είναι τυχαία ... ), η απάντηση είναι απλή. Είναι πολύ όμορφο, και χρήσιμο. Αν το τραβήξει κανείς, με αυτή τη μεθοδούλα που επιστρέφει το boolean ( μπορώ να συνεχίσω την εκτέλεση; ), μπορείς να δέσεις και να κάνεις synchronization μεθόδων, ουρές, multiple event handlers και chaining κτλ. κτλ. είναι ... execution chain & workflow παρεούλα, σε JavaScript παρακαλώ. Θέλει μόνο φαντασία :)

    Ελπίζω να μη βαρεθήκατε όσοι φτάσατε μέχρι το τέλος, καλό απόγευμά μας !

    O:]




    Angel
    O:]
  •  07-04-2009, 12:28 49925 σε απάντηση της 49915

    Απ: My JavaScript waitForEvent() nightmares ....

    Καλησπέρα φιλε Άγγελε...

    Διαβάζοντας το post σου, μου ήρθε στο μυαλό το παράδειγμα από το Wizard Book για discrete event simulation. Και σκέφτηκα ότι είναι καλή ευκαιρία να δώσω ένα link προς το άλλο σύμπαν Smile

    A Simulator for Digital Circuits

    Keep up the good code


    Palladinos Nick
    Software Engineer
    -----------------------
    The limits of my language mean the limits of my world. (Ludwig Wittgenstein)
  •  08-04-2009, 18:26 49971 σε απάντηση της 49925

    Απ: My JavaScript waitForEvent() nightmares ....

    Κι άκου τώρα πράματα ... πλέον λέει το setTimeout παίρνει ως πρώτη παράμετρο και ένα function, αρκεί να μην έχει παραμέτρους ... :P ... magic ... magic ...
    [ ε ρε τι τραβάμε οι 30+ που μάθαμε στοn Ι.Ε. 3 και Netscape Navigator ... όλα τα καλά τους δίνουν τώρα ! ]

    Angel
    O:]
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems