Подтвердить что ты не робот

Измените асинхронный диалог jQuery на синхронный?

В настоящее время я работаю над заменой "alert" / "confirm" в диалоговом окне jquery.

Но большинство устаревших кодов написано некоторым асинхронным способом, что затрудняет изменение. Есть ли способ заставить диалог jquery работать синхронно? (не используйте функцию цикла или обратного вызова)

   For example:
   function run()
   { 
      var result = confirm("yes or no");
      alert( result );
      \\more codes here
   }

В этом примере предупреждения и другие коды будут выполняться после выбора пользователя.

Если мы используем диалог jquery var result = $dialog.open() Он будет продолжать выполнять оповещение, которое является асинхронным.

В настоящее время моим решением является использование функции обратного вызова в функции OK | Отмена.       Например:

    OK: function ()
   {
       $dialog.close();
       alert("yes");
       //more codes here
    }

Этот метод работает, но сложно сделать все синхронные коды асинхронными, что требует значительных изменений (см. следующий пример). Итак, я ищу синхронный диалог jQuery, возможно ли это?

Например: (Реальные коды намного сложнее, чем в следующем примере)

     function f1()
    {
          if ( confirm("hello") )    f2();
          alert("no");
    } 

    function f2()
    {
          if( confirm("world") )    f3();
          alert("no");
    }

    function f3()
    {
          return confirm("!") ;
    }

Другой пример:

vendorObject.on('some-event', function() {
    if(confirm("Do you really want to do that?")) {
        return true;
    }
    else {
        return false; // cancel the event
    }
});

... здесь объект-продавец запускает событие, которое должно быть отменено, если пользователь подтверждает. Событие может быть отменено только в том случае, если обработчик события возвращает false - синхронно.

4b9b3361

Ответ 1

Короткий ответ - нет, вы не сможете синхронизировать свой код. Вот почему:

  • Для того, чтобы это было синхронно, выполняемый в настоящее время script должен был ждать, пока пользователь предоставит ввод, а затем продолжит.
  • Пока выполняется script, пользователь не может взаимодействовать с пользовательским интерфейсом. Фактически, пользовательский интерфейс даже не обновляется до тех пор, пока выполнение script не выполняется.
  • Если script не может продолжаться до тех пор, пока пользователь не предоставит ввод, и пользователь не сможет предоставить ввод до тех пор, пока script не будет завершен, ближайший вы когда-либо получите, это зависающий браузер.

Чтобы проиллюстрировать это поведение, отлаживайте свой код и задайте точку прерывания в строке, следующей за строкой, которая изменяет интерфейс:

$("body").css("backgroundColor", "red");
var x = 1;  // break on this line

Обратите внимание, что фон страницы еще не красный. Он не изменится на красный, пока вы не возобновите выполнение, а script завершит выполнение. Вы также не можете щелкнуть какие-либо ссылки на своей странице, пока у вас есть выполнение script, приостановленное с вашим отладчиком.

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

Хорошая новость заключается в том, что преобразовать свой код не очень сложно. Предположительно, ваш код в настоящее время выглядит примерно так:

if (confirm("continue?")) {
    // several lines of code if yes
}
else {
    // several lines of code if no
}
// several lines of code finally 

Ваша асинхронная версия может создать функцию ifConfirm(text, yesFn, noFn, finallyFn), и ваш код будет выглядеть примерно так:

ifConfirm("continue?", function () {
    // several lines of code if yes
},
function () {
    // several lines of code if no
},
function () {
    // several lines of code finally 
});

Изменить: В ответ на дополнительный пример, который вы добавили к своему вопросу, к сожалению, этот код нужно будет реорганизовать. Просто невозможно иметь синхронные пользовательские диалоговые окна подтверждения. Чтобы использовать диалоговое окно пользовательского подтверждения в сценарии, когда событие необходимо продолжить или отменить, вам просто нужно всегда отменить событие и воспроизвести событие в обратном вызове yesFn.

Например, ссылка:

$("a[href]").click(function (e) {
    e.preventDefault();
    var link = this.href;
    ifConfirm("Are you sure you want to leave this awesome page?", function () {
        location.href = link;
    });
});

Или форма:

$("form").submit(function (e) {
    e.preventDefault();
    var form = this;
    ifConfirm("Are you sure you're ready to submit this form?", function () {
        form.submit();
    });
});

Ответ 2

Я не совсем уверен, что мотивация, не использующая обратные вызовы, заключается в том, что трудно судить о том, какое решение может удовлетворить ваши требования, но другой способ отсрочить выполнение - через jQuery "отложенный" объект.

http://api.jquery.com/category/deferred-object/

Вы можете настроить функцию, которая открывает диалоговое окно jquery и добавить код, который "ждет" для закрытия диалогового окна. Это заканчивается тем, что работает аналогичным образом с обратным вызовом в случае, который вы выложили, но вот пример:

    function confirm () {
        var defer = $.Deferred(); 
        $('<div>Do you want to continue?</div>').dialog({
                autoOpen: true,
                close: function () { 
                    $(this).dialog('destroy');
                },
                position: ['left', 'top'],
                title: 'Continue?',
                buttons: {
                    "Yes": function() {
                        defer.resolve("yes"); //on Yes click, end deferred state successfully with yes value
                        $( this ).dialog( "close" );
                    },
                    "No": function() {
                        defer.resolve("no"); //on No click end deferred successfully with no value
                        $( this ).dialog( "close" );
                    }
                }
            });
        return defer.promise(); //important to return the deferred promise
    }

    $(document).ready(function () {
        $('#prod_btn').click(function () {
            confirm().then(function (answer) {//then will run if Yes or No is clicked
                alert('run all my code on '  + answer);

            });
        });

    });

Здесь он работает в jsFiddle: http://jsfiddle.net/FJMuJ/

Ответ 3

Нет, вы не можете ничего синхронизировать в Javascript (предупреждение на самом деле нарушает правила). Javascript построен с "однопоточным, асинхронным" в ядре.

Однако вы можете отключить функциональные возможности базовой страницы (лайтбокс), так что на странице не запускается событие, пока вы не примете диалоговое действие, будь то ОК или Отмена. Думал, это не поможет вам получить ваш код синхронизации. Вы должны переписать.

Ответ 4

Здесь некоторые идеи - то, что вы на самом деле хотите, это заблокировать ваше асинхронное событие, чтобы оно выглядело как синхронизация. Вот некоторые ссылки:

Ожидание асинхронных вызовов

Mobl

Описание JavaScript

Надеюсь, это поможет вам в дальнейшем!

Ответ 5

Чтобы ответить на вопрос Дэвида Уитмена, более конкретный вопрос, вот как я реализую "отложенную" обратную передачу для события ClickButton Click. В принципе, я просто предотвращаю поведение по умолчанию и запускаю обратную передачу вручную, когда пользовательская обратная связь доступна.

function MyClientClickHandler(event, confirmationMessage, yesText, noText) {
    // My LinkButtons are created dynamically, so I compute the caller ID
    var elementName = event.srcElement.id.replace(/_/g, '$');
    // I don't want the event to be fired immediately because I want to add a parameter based on user input
    event.preventDefault();
    $('<p>' + confirmationMessage + '</p>').dialog({
        buttons: [
        {
            text: yesText,
            click: function () {
                $(this).dialog("close");
                // Now I'm ready to fire the postback
                __doPostBack(elementName, 'Y');
            }
        },
        {
            text: noText,
            click: function () {
                $(this).dialog("close");
                // In my case, I need a postback when the user presses "no" as well
                __doPostBack(elementName, 'N');
            }
        }
        ]
    });
}

Ответ 6

Я действительно не понимаю, почему вы против использования обратных вызовов Jquery для достижения поведения в вашем примере. Вам обязательно придется переписать код, но что-то вроде:

    function f1() { 
    $( "#testdiv" ).dialog({
        modal: true,
        buttons: {
            "OK": function() {
                $( this ).dialog( "close" );
                f2();
            },
            Cancel: function() {
                $( this ).dialog( "close" );
                alert('no');
            }
        }
    });
}
function f2() {
      $( "#testdiv2" ).dialog({
        modal: true,
        buttons: {
            "OK": function() {
                $( this ).dialog( "close" );
                f3();
            },
            Cancel: function() {
                $( this ).dialog( "close" );
                alert('no');
            }
        }
    });
}
function f3() {
    $( "#testdiv3" ).dialog({
        modal: true,
        buttons: {
            "OK": function() {
                $( this ).dialog( "close" );
            },
            Cancel: function() {
                $( this ).dialog( "close" );
            }
        }
    });
}

    <div id="testdiv" title="Hello"/>
    <div id="testdiv2" title="World"/>
    <div id="testdiv3" title="!"/>