Javascript 将异步 jQuery Dialog 更改为同步?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6962301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change the asynchronous jQuery Dialog to be synchronous?
提问by user881284
Currently, I'm working to replace "alert'/"confirm" with the jquery dialog.
目前,我正在努力用 jquery 对话框替换“警报”/“确认”。
But most of legacy codes is written in some asynchronous way, which make it difficult to change. Is there any way to make jquery dialog work in a synchronous way? ( don't use loop or callback function )
但是大多数遗留代码都是以某种异步方式编写的,这使得更改变得困难。有没有办法让 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.
在这个例子中,警报和其他代码将在用户选择后执行。
If we use jquery dialog var result = $dialog.open() It will continue to execute the alert, which is asynchronous.
如果我们使用jquery dialog var result = $dialog.open() 会继续执行alert,这是异步的。
Currently, my solution is to use call back function in the OK|Cancel function. For example:
目前,我的解决方案是在 OK|Cancel 函数中使用回调函数。例如:
OK: function ()
{
$dialog.close();
alert("yes");
//more codes here
}
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??
这种方法有效,但是很难让所有的同步代码都变成异步的,这需要大量的修改(见下面的例子)。所以我正在寻找同步 jQuery Dialog,这可能吗??
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
}
});
... 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.
...这里供应商对象触发一个事件,如果用户确认,则必须取消该事件。只有当事件处理程序false
同步返回时,才能取消该事件。
回答by gilly3
The short answer is no, you won't be able to keep your code synchronous. Here's why:
简短的回答是否定的,您将无法保持代码同步。原因如下:
- In order for this to be synchronous, the currently executing script would have to wait for the user to provide input, and then continue.
- While there is a currently executing script, the user is unable to interact with the UI. In fact, the UI doesn't even update until after the script is done executing.
- If the script can't continue until the user provides input, and the user can't provide input until the script is finished, the closest you'll ever get is a hung browser.
- 为了使其同步,当前执行的脚本必须等待用户提供输入,然后继续。
- 当有当前正在执行的脚本时,用户无法与 UI 交互。事实上,UI 甚至在脚本执行完成后才会更新。
- 如果在用户提供输入之前脚本无法继续,并且在脚本完成之前用户无法提供输入,那么您将获得的最接近的是一个挂起的浏览器。
To illustrate this behavior, debug your code and set a break point on the line following a line that changes the UI:
为了说明这种行为,请调试您的代码并在更改 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.
请注意,您的页面背景还不是红色。在您恢复执行并且脚本完成执行之前,它不会变为红色。当您的调试器暂停执行脚本时,您也无法单击页面中的任何链接。
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.
对于alert()
和,此规则有一个例外confirm()
。这些是浏览器控件,与实际网页 UI 元素的处理方式不同。
The good newsis 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
Your asynchronous version could create a function ifConfirm(text, yesFn, noFn, finallyFn)
and your code would look very much the same:
您的异步版本可以创建一个函数,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
});
Edit:In response to the additional example you added to your question, unfortunately that code will need to be refactored. It is simply not possibleto 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.
编辑:为了回应您添加到问题中的附加示例,不幸的是,该代码需要重构。根本不可能有同步的自定义确认对话框。要在事件需要继续或取消的场景中使用自定义确认对话框,您只需始终取消该事件并在yesFn
回调中模拟该事件。
For example, a link:
例如,一个链接:
$("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;
});
});
Or, a form:
或者,一个表格:
$("form").submit(function (e) {
e.preventDefault();
var form = this;
ifConfirm("Are you sure you're ready to submit this form?", function () {
form.submit();
});
});
回答by Ben L
I'm not exactly sure what the motivation behind not using callbacks is so it is hard to judge what solution might satisfy your requirements, but another way to delay execution is through jQuery's "deferred" object.
我不确定不使用回调背后的动机是什么,因此很难判断哪种解决方案可能满足您的要求,但另一种延迟执行的方法是通过 jQuery 的“延迟”对象。
http://api.jquery.com/category/deferred-object/
http://api.jquery.com/category/deferred-object/
You could set up a function that opens the jquery dialog and add code that "waits" for dialog to close. This ends up working in a fairly similar way to a callback in the case you've laid out but here is an example:
您可以设置一个函数来打开 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);
});
});
});
Here it is working in jsFiddle: http://jsfiddle.net/FJMuJ/
它在 jsFiddle 中工作:http: //jsfiddle.net/FJMuJ/
回答by Ben L
No, you can't do anything sync in Javascript (alert is breaking the rules, in fact). Javascript is built with "single threaded, async" in the core.
不,您不能在 Javascript 中进行任何同步(实际上,警报正在违反规则)。Javascript 以“单线程、异步”为核心构建。
What you can do, though, is disable functionality of the underlying page (lightbox-like) so no event get triggered from the page until you don't take the dialog action, be it OK or Cancel. Thought this does not help you to get your sync code working. You have to rewrite.
但是,您可以做的是禁用基础页面(类似灯箱)的功能,因此在您不执行对话框操作(无论是确定还是取消)之前,不会从页面触发任何事件。认为这对您的同步代码没有帮助。你必须重写。
回答by Leon
Here's some ideas - what you actually want is to block your async event to make it look like sync. Here's some links:
这里有一些想法 - 您真正想要的是阻止异步事件以使其看起来像同步。这是一些链接:
Hope this helps you further!!
希望这对你有帮助!!
回答by Sue Maurizio
To answer David Whiteman's more specific question, here's how I'm implementing a "deferred" postback for a LinkButton Click event. Basically, I'm just preventing the default behaviour and firing the postback manually when user feedback is available.
为了回答大卫怀特曼更具体的问题,这里是我如何为 LinkButton Click 事件实现“延迟”回发。基本上,我只是阻止默认行为并在用户反馈可用时手动触发回发。
function MyClientClickHandler(event, confirmationMessage, yesText, noText) {
// My LinkButtons are created dynamically, so I compute the caller's 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's 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');
}
}
]
});
}
回答by Kelli Curiotto
You can use a real modal dialog.
您可以使用真正的模态对话框。
[dialog] is an element for a popup box in a web page, including a modal option which will make the rest of the page inert during use. This could be useful to block a user's interaction until they give you a response, or to confirm an action.
[dialog] 是网页中弹出框的一个元素,包括一个模式选项,该选项将使页面的其余部分在使用过程中处于惰性状态。这对于阻止用户的交互直到他们给您响应或确认操作非常有用。
回答by Jon
I don't really see why you are opposed to using Jquery callbacks to achieve the behavior in your example. You will definitely have to rewrite some code but something like:
我真的不明白您为什么反对使用 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="!"/>