Можете ли вы дождаться обратного вызова javascript?

Я пытаюсь использовать диалоговую библиотеку предупреждений jQuery из http://abeautifulsite.net/notebook/87 вместо предупреждений по умолчанию (которые выглядят довольно ужасно на мой взгляд). Кажется, это отличная библиотека, но нет примера использования библиотеки 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:

Я опубликовал комментарий на веб-сайте плагина (только сегодня утром), и Google искал javascript и ожидал завершения обратного вызова без каких-либо результатов.

Любые идеи о том, как правильно использовать обратный вызов, чтобы получить результат, до выполнения всех остальных javascript?

Спасибо.

Ответ 1

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

Это приводит к непониманию последовательности событий, которые происходят с использованием асинхронного кода. Просто потому, что вы написали его в строке, это не значит, что он будет выполняться строго сверху вниз.

  • jConfirm вызывается, получая функцию как один из ее параметров, который он запоминает.
  • jConfirm отображает свой пользовательский интерфейс на странице и немедленно возвращается.
  • Выполняется строка 'if (response == true)'. Действительно, это должно просто читать "if (response)", логическое сравнение излишнее. Но в любом случае ответ, конечно, ложный. Ваша функция отбрасывает и завершает работу, предоставляя управление браузеру.
  • Пользователь нажимает jConfirm UI.
  • jConfirm только теперь переходит в действие и вызывает функцию, которую вы ей дали, и она помнила ранее.
  • Вложенная функция устанавливает ответ true, слишком поздно для условия if (response == true), чтобы что-либо сделать с ним.

В качестве альтернативы вы написали "//wait for response", но нет кода JavaScript, который вы можете написать, который на самом деле это сделает. Ваша функция должна вернуться, чтобы вернуть управление браузеру, прежде чем браузер сможет запустить события кликов на пользовательском интерфейсе jConfirm, чтобы продолжить обработку.

Способы работы асинхронного кода в синхронном контексте (и наоборот) существуют - в частности, потоки и сопрограммы (и их генераторы ограниченного отношения). Но JavaScript не имеет ни одной из этих функций, поэтому вы должны написать свой код в соответствии с синхронно-асинхронной моделью, используемой вашей библиотекой.

Ответ 2

Вы только что натолкнулись на большое ограничение 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');
})

Ответ 3

Поскольку обратный вызов является асинхронным (по крайней мере, в том смысле, что он ждет, когда пользователь что-то сделает), может быть проще обрабатывать то, что вам нужно, в обратном вызове:

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

@klogan [комментарии]

Я предполагаю, что вы получили их от здесь?

Страница дает вам ответ: (смотрите Использование)

Эти методы не возвращают те же значения, что и confirm() и prompt(). Вы должны получить доступ к результирующим значениям с помощью функции обратного вызова. (Подробнее см. Демонстрацию.)


@klogan

То, что я пытаюсь сделать, заключается в том, что на самом деле нет простого способа выполнить то, что вы хотите. Вы пытаетесь сопоставить процедурный и управляемый событиями программирование - что-то не поможет вам JavaScript.

<я > Простейшим (хотя, рискованным) решением является использование псевдо-бесконечного цикла. Но, если 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;
}

удаp >

Ответ 4

Технически, да, но я бы не сделал этого на веб-сайте.

Взгляните на описательный JavaScript, основанный на Narcissus.

Нарративный JavaScript - это небольшое расширение языка JavaScript, которое позволяет блокировать возможности для асинхронных обратных вызовов событий. Это делает асинхронный код обновляемым и понятным.

Selenium использует эту технологию.


Update

Отъезд Строки JavaScript:

JavaScript Strands добавляет сопрограммы и совместная резьбовая поддержка Язык JavaScript для блокировки возможности для асинхронного события Обратные вызовы. Это делает код, который использует асинхронную работу более линейный, читаемый и управляемый. Строки построены по описанию JavaScript, написанный Neil Mix, и большая часть описательного JavaScript остался в Strands, включая большую часть этой документации.

В JavaScript ваш код не может просто дождитесь окончания события - событие всегда должно обрабатываться отдельный, асинхронный обработчик событий. Иногда это нормально, но часто заставляет то, что должно быть простым последовательность утверждений в gnarly искажения. Он также нарушает способность инкапсулировать функциональность потому что вызывающие функции должны знать предоставить обработчик обратного вызова. Пряди обеспечивает возможность приостанавливать и возобновить потоки исполнения. выполнение может приостановить возобновление, когда событие законченный. Это позволяет вам писать трудно читаемое асинхронное событие обработка в простых, линейных, читаемых код, который инкапсулирует реализацию.

Ответ 5

Я бы предположил, что вам нужно будет отхватить ответ так. Я не думаю, что вам нужен обратный вызов.

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

Ответ 6

Думаю, я придумал возможное решение этой проблемы. Я читал эту статью: http://treasure4developer.wordpress.com/2008/06/23/calling-postback-event-from-javascript/

В принципе, идея состоит в том, что вы принудительно возвращаете postback из javascript, сначала я обнаружил, что postback будет работать, но не будет вызывать событие с моей кнопкой, но после прочтения статьи я обнаружил, что могу определить, была ли это обратная передача javascript и просто вызовите метод для обработки

С уважением DotnetShadow

Ответ 7

Как говорили парни, нет пути! но... как мы говорим в моей стране (Бразилия), ле гамби:

мы можем сделать что-то вроде этого:

<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.

Пока, и я надеюсь, что это может помочь кому-то.

Ответ 8

Эта вещь работает. Требуется 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;
}

Ответ 9

Подумайте о обратных вызовах как отправке сообщений, и это приведет к лучшей структуре вашего кода.