web-dev-qa-db-fra.com

Pouvez-vous attendre le rappel javascript?

J'essaie d'utiliser la bibliothèque de boîtes de dialogue d'alertes jQuery à partir de http://abeautifulsite.net/notebook/87 au lieu des alertes par défaut (qui sont plutôt abominables à mon avis). Cela semble être une excellente bibliothèque, mais il n'y a pas d'exemple d'utilisation de la bibliothèque jConfirm.

J'ai besoin de faire quelque chose comme ça:

function confirm() {
        var result = false;
        var response = false;
        jConfirm('are you sure?', 'Confirmation Dialog',
          function(r) {
            result = r;
            response = true;
            return r;
        });
        if (response == true) {
            alert(result);
            return result;
        }
        else {
            //wait for response
            alert('hi');
        }
    }

et mon appel de mon bouton .net:

J'ai posté un commentaire sur le site Web du plugin (ce matin seulement) et Google a effectué une recherche javascript et a attendu qu'un rappel soit terminé sans aucun résultat.

Des idées sur la façon d'utiliser correctement le rappel pour obtenir le résultat, avant que le reste du javascript soit exécuté?

Merci.

22
Aligned
jConfirm('are you sure?', 'Confirmation Dialog',
    function(r) {
        result = r;
        response = true;
        return r;
    }
);
if (response == true) {

Cela trahit une incompréhension de la séquence d'événements qui se produit à l'aide d'un code asynchrone. Ce n’est pas parce que vous l’avez écrit en ligne qu’il va s’exécuter strictement de haut en bas.

  1. jConfirm est appelé, recevant une fonction parmi ses paramètres, dont il se souvient.
  2. jConfirm affiche son interface utilisateur sur la page et revient immédiatement.
  3. La ligne 'if (response == true)' est exécutée. Vraiment, cela devrait simplement se lire "si (réponse)", la comparaison booléenne est superflue. Mais dans tous les cas, la réponse est bien sûr fausse. Votre fonction abandonne et quitte, rendant le contrôle au navigateur.
  4. L'utilisateur clique sur l'interface utilisateur de jConfirm.
  5. jConfirmer ne fait que passer à l’action et rappeler la fonction que vous lui avez attribuée.
  6. Votre fonction imbriquée donne la valeur true à la réponse, bien trop tard pour que la condition 'if (response == true)' fasse quoi que ce soit avec elle.

Vous avez écrit "// wait for response" comme alternative, mais vous ne pouvez écrire aucun code JavaScript capable de le faire. Votre fonction doit revenir pour redonner le contrôle au navigateur, avant que celui-ci puisse déclencher les événements de clic sur l'interface utilisateur jConfirm qui permettent le traitement.

Il existe des moyens de faire fonctionner le code asynchrone dans un contexte synchrone (et inversement) - en particulier des threads et des coroutines (et leurs générateurs de relations limitées). Mais JavaScript ne possède aucune de ces fonctionnalités. Vous devez donc écrire votre code pour qu'il corresponde au modèle synchrone ou asynchrone utilisé par votre bibliothèque.

16
bobince

Vous venez de frapper une grosse limite en JavaScript. Une fois que votre code entre dans le monde asynchrone, il n’ya aucun moyen de revenir à un flux d’exécution procédurale classique.

Dans votre exemple, la solution serait de faire une boucle en attendant que la réponse soit remplie. Le problème est que JavaScript ne fournit aucune instruction qui vous permette de boucler indéfiniment sans prendre 100% de la puissance de traitement. Donc, vous finirez par bloquer le navigateur, parfois au point que votre utilisateur ne pourra plus répondre à la question.

La seule solution consiste à s’en tenir au modèle asynchrone et à le conserver. Mon conseil est que vous devriez ajouter un rappel à toute fonction devant effectuer un travail asynchrone afin que l'appelant puisse exécuter quelque chose à la fin de votre fonction.

function confirm(fnCallback) 
{
    jConfirm('are you sure?', 'Confirmation Dialog', function(r) 
    {
        // Do something with r 

        fnCallback && fnCallback(r); // call the callback if provided
    });
}

// in the caller

alert('begin');

confirm(function(r)
{
    alert(r);

    alert('end');
})
19
Vincent Robert

Techniquement, oui, mais je ne le ferais pas sur un site Web.

Jetez un coup d'œil à JavaScript narratif , qui est basé sur Narcisse .

JavaScript narratif est une petite extension du langage JavaScript qui permet de bloquer les rappels d’événements asynchrones. Cela rend le code asynchrone lisible et compréhensible de façon rafraîchissante. 

Selenium utilise cette technologie.


Mettre à jour

Découvrez JavaScript Strands :

JavaScript Strands ajoute la coroutine et support de filetage coopératif au Langage JavaScript pour activer le blocage capacités pour l'événement asynchrone rappels. Cela rend le code que utilise beaucoup le fonctionnement asynchrone plus linéaire, lisible et gérable . Strands est construit sur Narrative JavaScript écrit par Neil Mix, et beaucoup de JavaScript narratif a resté dans les brins, y compris beaucoup de cette documentation.

En JavaScript, votre code ne peut pas simplement attendez qu'un événement se soit déclenché - le événement doit toujours être géré par un gestionnaire d'événements asynchrone séparé . Parfois cela va, mais souvent force ce qui devrait être un simple séquence de déclarations en noueux des contorsions. Cela casse aussi le capacité à encapsuler la fonctionnalité parce que les fonctions d'appel doivent savoir pour fournir un gestionnaire de rappel. Brins offre la possibilité de suspendre et reprendre les threads d'exécution. Exécution peut suspendre la reprise lorsque l'événement est fini. Cela vous permet d'écrire événement asynchrone difficile à lire manipulation simple, linéaire, lisible code qui encapsule l'implémentation.

5
Ates Goral

Cette chose fonctionne. A besoin de jQuery.

function myconfirm(kyssa, Elm, e){ // neG
    if(jQuery('#confirmquestion').data('result')){
        var V = jQuery('#confirmquestion').data('result');
        jQuery('#confirmquestion').remove(); 
        return V == 'Y' ? true : false;         
    }else if(!jQuery('#confirmquestion').length){
        jQuery('body').append('<div id="confirmquestion">'+
        '<h4>Kinnitus</h4>'+
        '<div id="kyssa">'+kyssa+'</div>'+
        '<center>'+
        '<button onclick="jQuery(\'#confirmquestion\').data(\'result\', \'Y\');">Jah</button>&nbsp;'+
        '<button onclick="jQuery(\'#confirmquestion\').data(\'result\', \'N\');">Ei</button></div>'+
        '</center>');
        jQuery('#confirmquestion button').click(function(){
            jQuery(Elm).trigger(e.type);
        })
    }       
    return false;
}

onChange="if(myconfirm(\'Saada kiri: \'+jQuery(this).find(\'option:selected\').html()+\' ?\', this, event)) { ... }"

CSS

#confirmquestion{
    border:1px solid #999;
    background:white;
    padding-bottom: 30px;
    position:fixed;
    width:300px;
    font-size:12px;
    top:45%;
    left:50%;
    margin-left:-150px;
}

#confirmquestion h4 {
    background:blue;
    color:white;
    margin:0;
    padding: 2px 5px;
    border-bottom:#777; 
    text-align:center;
}

#confirmquestion #kyssa {
    padding: 30px 25px;
}
0
neG

Comment les gars ont dit, il n'y a pas moyen! mais ... comme on dit dans mon pays (le Brésil), le gambi:

nous pouvons faire quelque chose comme ça:

<h:commandLink styleClass="linkValor xExcluir" value="x"  
                     onclick="if(confirmar('Confirmar excluir.','Deseja realmente excluir este registro?', this)) return true; else return false;"
                     action="#{mBeanPesquisarLinhas.excluir}"/>

et le javascript:

function confirmar(titulo, msg, elemento) { 

    if ($(elemento).attr('sim')) {      
        $(elemento).removeAttr('sim');      
        return true;
    } else if ($(elemento).attr('nao')) {       
        $(elemento).removeAttr('nao');      
        return false;
    } else {
        $("#dialog-confirm").html('<p>' + msg + '</p>').dialog({
            resizable : false,
            height : 200,
            modal : true,
            title : titulo,
            buttons : {
                "Sim" : function() {
                    $(this).dialog("close");
                    $(elemento).attr('sim', 'sim');
                    $(elemento).click();
                },
                "Não" : function() {
                    $(this).dialog("close");
                    $(elemento).attr('nao', 'nao');
                    $(elemento).click();
                }
            }
        });
    }

    return false;
}

c'est le même problème mais en utilisant jquery-ui.

Au revoir et j'espère que cela peut aider quelqu'un.

0
MaikoID

Je suppose que vous devrez saisir la réponse comme ceci. Je ne pense pas que vous ayez besoin d'un rappel.

function confirm() {
        var response = jConfirm('are you sure?', 'Confirmation Dialog');
        if (response) {
            alert(result);
        }
        else {
            //wait for response
            alert('hi');
        }
    }

Je pense avoir trouvé une solution possible à ce problème. Je lisais cet article: http://treasure4developer.wordpress.com/2008/06/23/calling-postback-event-from-javascript/

Fondamentalement, l’idée est de forcer la publication à partir de javascript. Au début, j’ai trouvé que la publication fonctionnait, mais n’appelait pas mon événement de bouton, mais après avoir lu l’article, j’ai découvert que je pouvais détecter s’il s’agissait de postback javascript et simplement appeler un méthode pour faire le traitement

Cordialement DotnetShadow

0
DotnetShadow

Pensez aux rappels comme à l'envoi de messages, ce qui donnera une meilleure structure à votre code. 

0