web-dev-qa-db-ja.com

JavaScriptコールバックを待つことができますか?

私は http://abeautifulsite.net/notebook/87 のjQueryアラートダイアログライブラリをデフォルトのアラート(私の意見ではかなりひどく見えます)の代わりに使用しようとしています。これはすばらしいライブラリのようですが、jConfirmライブラリの使用例はありません。

私はこのようなことをする必要があります:

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');
        }
    }

そして私の.netボタンからの私の呼び出し:

プラグインのWebサイトにコメントを投稿し(今朝のみ)、GoogleでJavaScriptを検索し、コールバックが完了して結果が得られないのを待っていました。

JavaScriptの残りの部分が実行される前に、コールバックを正しく使用して結果を取得する方法に関するアイデアはありますか?

ありがとう。

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

これは、非同期コードを使用して発生する一連のイベントの誤解を裏付けています。インラインで記述したからといって、厳密に上から下に実行されるわけではありません。

  1. jConfirmが呼び出され、パラメータの1つとして関数を受け取り、それを記憶します。
  2. jConfirmは、UIをページに表示し、すぐに戻ります。
  3. 「if(response == true)」行が実行されます。本当にこれは 'if(response)'と読むべきです、ブール値の比較は不必要です。しかし、いずれの場合でも、応答はもちろん偽です。関数は放棄して終了し、制御をブラウザーに戻します。
  4. ユーザーがjConfirmのUIをクリックします。
  5. jConfirmが動作するようになり、指定した関数が呼び出されて、以前に記憶されていた。
  6. ネストされた関数は応答をtrueに設定しますが、「if(response == true)」条件でそれを実行するには遅すぎます。

代わりに "// wait for response"を記述しましたが、実際にそれを行うJavaScriptコードは記述できません。ブラウザーがjConfirm UIでクリックイベントを発生させて処理を続行する前に、関数は制御をブラウザーに戻す必要があります。

非同期コードを同期コンテキスト(およびその逆)で動作させる方法が存在します-特にスレッドとコルーチン(およびそれらの制限された関係ジェネレーター)。ただし、JavaScriptにはこれらの機能がないため、ライブラリが使用している同期モデルまたは非同期モデルに適合するようにコードを記述する必要があります。

16
bobince

JavaScriptの大きな制限に達しました。コードが非同期の世界に入ると、従来の手続き型実行フローに戻る方法はありません。

あなたの例では、解決策は、応答が満たされるのを待つループを作ることです。問題は、JavaScriptが100%の処理能力を使用せずに無限にループできるようにする命令を提供しないことです。そのため、ブラウザをブロックしてしまい、場合によっては、ユーザーが実際の質問に答えられなくなることがあります。

ここでの唯一の解決策は、非同期モデルに固執してそれを維持することです。私のアドバイスは、非同期処理を実行する必要がある関数にコールバックを追加して、呼び出し元が関数の最後で何かを実行できるようにすることです。

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

コールバックは非同期であるため(少なくとも、ユーザーが何かをするのを待っているという意味で)、コールバック内で必要なものを処理する方が簡単な場合があります。

function confirm() {
    jConfirm('are you sure?', 'Confirmation Dialog', function(r) {
        if (r) doSomething();
    });
}

@klogan [コメント]

これらは here から取得したと思います。

ページはあなたにあなたの答えを与えます:(Usageを見てください)

これらのメソッドは、confirm()およびPrompt()と同じ値を返しません。コールバック関数を使用して、結果の値にアクセスする必要があります。 (詳細については、デモを参照してください。)


@klogan

私が作ろうとしているポイントは、あなたが望むものを達成するための本当に簡単な方法はないということです。 手続き型イベント駆動型プログラミングを相互に関連付けようとしています- JavaScriptが役に立たない何か。

最も単純な(ただし、risky)ソリューションは、疑似無限ループを使用することです。ただし、callbackが呼び出されない場合は、実際に無限ループになります。また、JavaScriptエンジンによっては、待機しているブラウザーを強制終了する場合があります。

ポイント:あなたの最善の策は避けることです この イベント駆動型を手続き型に強制しようとしています。

function confirm() {
    var result = false;
    var response = false;

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

    while(!response) continue; // wait
    return result;
}
8

技術的にはyesですが、ウェブサイトではそうしません。

Narrative JavaScript を見てください。これは Narcissus に基づいています。

ナラティブJavaScriptは、JavaScriptイベントの小さな拡張機能であり、非同期イベントコールバックのブロック機能を有効にします。これにより、非同期コードが読みやすく読みやすくなります。

Selenium このテクノロジーを使用します。


更新

チェックアウト JavaScript Strands

JavaScript Strandsは、コルーチンおよび協調スレッディングサポートをJavaScript言語に追加して、非同期イベントコールバックのブロック機能を有効にします。これにより、非同期操作を利用するコードがより線形で、読みやすく、管理しやすくなります。 Strandsは、Neil Mixによって記述されたNarrative JavaScriptに基づいて構築されており、Narrative JavaScriptの多くは、このドキュメントの多くを含めてStrandsに残っています。

JavaScriptでは、コードはイベントが発生するまで単純に待機することはできません。イベントは常に別個の非同期イベントハンドラーによって処理される必要があります。これで問題ないこともありますが、多くの場合、単純な一連のステートメントであるはずの内容が危険なゆがみに陥ります。また、コールバックハンドラーを提供するために関数を呼び出す必要があるため、機能をカプセル化する機能が損なわれます。 Strandsは、実行のスレッドを一時停止および再開する機能を提供します。イベントが終了すると、実行は再開を一時停止できます。これにより、実装をカプセル化するシンプルで線形で読み取り可能なコードで、読み取りにくい非同期イベント処理を記述できます。

5
Ates Goral

このことはうまくいきます。 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

男たちの言い方、方法はありません!しかし...私の国(ブラジル)では、ルガンビがどのように言うか

私たちはそれのようなことをすることができます:

<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}"/>

そして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;
}

同じ問題ですが、jquery-uiを使用しています。

さようなら、これが誰かの役に立つことを願っています。

0
MaikoID

このような応答を取得する必要があると思います。コールバックは必要ないと思います。

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

私はこの問題の可能な解決策を考え出したと思います。私はこの記事を読んでいました: http://treasure4developer.wordpress.com/2008/06/23/calling-postback-event-from-javascript/

基本的には、JavaScriptからポストバックを強制するという考えです。最初はポストバックは機能するがボタンイベントを呼び出せないことがわかりましたが、記事を読んだ後、それがJavaScriptポストバックであるかどうかを検出して、処理を行うメソッド

よろしくDotnetShadow

0
DotnetShadow

コールバックをメッセージの送信と見なすと、コードの構造が改善されます。

0