将异步 jQuery Dialog 更改为同步?

目前,我正在努力用 jquery 对话框替换alert"/confirm".

Currently, I'm working to replace "alert'/"confirm" with the jquery dialog.

但是大多数遗留代码都是以某种异步方式编写的,这使得更改变得困难.有什么方法可以使 jquery 对话框以同步方式工作?(不要使用循环或回调函数)

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

在此示例中,警报和其他代码将在用户选择后执行.

In this example the alert and other codes will be executed after user's choice.

如果我们使用 jquery 对话框var 结果 = $dialog.open()它将继续执行警报,这是异步的.

If we use jquery dialog var result = $dialog.open() It will continue to execute the alert, which is asynchronous.

目前,我的解决方案是在 OK|Cancel 函数中使用回调函数.例如:

Currently, my solution is to use call back function in the OK|Cancel function. For example:

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

这种方法可行,但是很难让所有同步的代码都变成异步的,需要做很多改动(见下例).所以我在找同步的jQuery Dialog,可以吗??

This method works but it is difficult to make all the synchronous codes become asynchronous, which requires a lot of change (see the following example). So I'm looking for the synchronous jQuery Dialog, is it possible??

例如:(实际代码比下面的例子复杂得多)

For example: ( The real codes are much more complicated than the following example)

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

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

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

<小时>

另一个例子:


Another example:

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

...这里供应商对象触发一个事件,如果用户确认,则必须取消该事件.只有当事件处理程序返回 false - 同步时,才能取消事件.

... here the vendor object fires an event, which has to be cancelled if the user confirms. The event can only be cancelled if the event handler returns false - synchronously.

推荐答案

简短的回答是不,你将无法保持你的代码同步.原因如下:

The short answer is no, you won't be able to keep your code synchronous. Here's why:

  • 为了使其同步,当前执行的脚本必须等待用户提供输入,然后继续.
  • 虽然当前正在执行脚本,但用户无法与 UI 交互.事实上,直到脚本执行完毕后,用户界面才会更新.
  • 如果脚本在用户提供输入之前无法继续,并且用户在脚本完成之前无法提供输入,那么您最接近的就是浏览器挂起.

为说明此行为,请调试您的代码并在更改 UI 的行之后的行上设置断点:

To illustrate this behavior, debug your code and set a break point on the line following a line that changes the UI:

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

请注意,您的页面背景还不是红色.在您恢复执行并且脚本完成执行之前,它不会变为红色.当您使用调试器暂停脚本执行时,您也无法单击页面中的任何链接.

Notice that your page background is not yet red. It won't change to red until you resume execution and the script finishes executing. You are also unable to click any links in your page while you've got script execution paused with your debugger.

alert()confirm() 有一个例外.这些是浏览器控件,其处理方式与实际网页 UI 元素不同.

There is an exception to this rule for alert() and confirm(). These are browser controls, and are treated differently than actual web page UI elements.

好消息是转换您的代码真的应该不是很难.大概,您的代码目前看起来像这样:

The good news is that it really shouldn't be very hard to convert your code. Presumably, your code currently looks something like this:

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) 并且您的代码看起来非常相似:

Your asynchronous version could create a function ifConfirm(text, yesFn, noFn, finallyFn) and your code would look very much the same:

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

为了回应您添加到问题中的其他示例,不幸的是,该代码需要重构.不可能有同步的自定义确认对话框.要在事件需要继续或取消的情况下使用自定义确认对话框,您只需始终取消事件并在 yesFn 回调中模拟事件.

In response to the additional example you added to your question, unfortunately that code will need to be refactored. It is simply not possible to have synchronous custom confirmation dialogs. To use a custom confirmation dialog in the scenario where an event needs to either continue or cancel, you'll just have to always cancel the event and mimic the event in the yesFn callback.

例如一个链接:

$("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();
    });
});

相关文章