22

我正在尝试使用来自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 按钮呼叫:

我已经在插件的网站上发表了评论(就在今天早上),谷歌搜索了 javascript 并等待回调完成但没有结果。

在其余的javascript执行之前,关于如何正确使用回调来获得结果的任何想法?

谢谢。

4

9 回答 9

19

您刚刚在 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');
})
于 2009-01-12T22:10:30.103 回答
16
jConfirm('are you sure?', 'Confirmation Dialog',
    function(r) {
        result = r;
        response = true;
        return r;
    }
);
if (response == true) {

这暴露了对使用异步代码发生的事件顺序的误解。仅仅因为您已经将它内联并不意味着它将严格自上而下地执行。

  1. jConfirm 被调用,接收一个函数作为它的参数之一,它记住了。
  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 没有这些特性,因此您必须编写代码以适应您的库正在使用的同步或异步模型。

于 2009-01-12T21:41:30.177 回答
8

由于回调是异步的(至少在等待用户做某事的意义上),在回调中处理您需要的内容可能更容易:

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

@klogan [评论]

我假设你从这里得到这些?

该页面为您提供答案:(在Usage下查看)

这些方法不返回与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;
}

于 2009-01-12T19:36:57.450 回答
5

从技术上讲,的,但我不会在网站上这样做。

看看Narrative JavaScript,它基于Narcissus

Narrative JavaScript 是 JavaScript 语言的一个小扩展,它支持异步事件回调的阻塞功能。这使得异步代码具有令人耳目一新的可读性和可理解性。

Selenium使用这种技术。


更新

查看JavaScript 链

JavaScript Strands 为 JavaScript 语言添加了协程和协作线程支持,以启用异步事件回调的阻塞功能。这使得使用异步操作的代码更加线性、可读和可管理。Strands 是基于 Neil Mix 编写的 Narrative JavaScript 构建的,并且大部分 Narrative JavaScript 都保留在 Strands 中,包括本文档的大部分内容。

在 JavaScript 中,您的代码不能简单地等到事件触发 - 事件必须始终由单独的异步事件处理程序处理。有时这很好,但它经常迫使应该是一个简单的语句序列变成粗糙的扭曲。它还破坏了封装功能的能力,因为调用函数必须知道提供回调处理程序。Strands 提供了暂停和恢复执行线程的能力。执行可以在事件完成时暂停恢复。这允许您以封装实现的简单、线性、可读的代码编写难以阅读的异步事件处理。

于 2009-01-12T19:50:07.470 回答
0

我会假设你必须抓住这样的回应。我认为你不需要回调。

function confirm() {
        var response = jConfirm('are you sure?', 'Confirmation Dialog');
        if (response) {
            alert(result);
        }
        else {
            //wait for response
            alert('hi');
        }
    }
于 2009-01-12T19:19:31.680 回答
0

我想我已经想出了解决这个问题的可能方法。我正在阅读这篇文章: http ://treasure4developer.wordpress.com/2008/06/23/calling-postback-event-from-javascript/

基本上这个想法是你从javascript强制回发,起初我发现回发可以工作但不会调用我的按钮事件,但在阅读文章后我发现我可以检测它是否是javascript回发并调用处理方法

问候 DotnetShadow

于 2009-01-14T05:48:51.240 回答
0

大佬们怎么说的,没办法!但是......我们在我的国家(巴西)怎么说,le gambi:

我们可以做类似的事情:

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

再见,我希望这可以帮助某人。

于 2011-10-11T18:15:51.387 回答
0

这东西行得通。需要 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;
}
于 2012-01-10T10:11:12.337 回答
0

将回调视为发送消息,它将在您的代码中产生更好的结构。

于 2012-03-08T04:11:49.857 回答