你能等待javascript回调吗?

时间:2009-01-12 19:13:55

标签: javascript jquery dialog callback confirm

我正在尝试使用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执行之前,有关如何正确使用回调来获取结果的任何想法?

感谢。

9 个答案:

答案 0 :(得分: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');
})

答案 1 :(得分: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的用户界面。
  5. j确认现在只是跳转到行动并回复你给它的功能,并且它早些时候记得。
  6. 您的嵌套函数将响应设置为true,对于'if(response == true)'条件来说,使用它做任何事都为时已晚。
  7. 您已经编写了“//等待响应”作为替代方案,但是没有可以编写的JavaScript代码实际上会这样做。在浏览器触发jConfirm UI上的点击事件以使处理继续之前,您的函数必须返回以将控制权交还给浏览器。

    存在使异步代码在同步上下文中工作(反之亦然)的方法 - 特别是线程和协程(及其有限的关系生成器)。但JavaScript没有这些功能,因此您必须编写代码以适应您的库正在使用的同步或异步模型。

答案 2 :(得分:8)

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

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

@klogan [评论]

我假设你从here得到了这些?

该页面为您提供答案:(查看用法

  

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

<击>的

答案 3 :(得分:5)

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

查看基于Narrative JavaScriptNarcissus

  

Narrative JavaScript是JavaScript语言的一个小扩展,它支持异步事件回调的阻塞功能。这使得异步代码清晰可读且易于理解。

Selenium使用此技术。


更新

结帐JavaScript Strands

  

JavaScript Strands添加了coroutine和   合作线程支持   JavaScript语言启用阻止   异步事件的功能   回调。这使得代码成为了   很多地使用异步操作   更线性,可读和可管理。   Strands建立在叙事之上   由Neil Mix编写的JavaScript,和   很多叙事JavaScript都有   留在Strands,包括很多   这个文件。

     

在JavaScript中,您的代码不能简单   等到一个事件被解雇了 -   事件必须始终由a处理   独立的异步事件处理程序。   有时这很好,但经常   强迫什么应该是简单的   一系列陈述变成了粗糙的   扭曲。它也打破了   封装功能的能力   因为调用函数必须知道   提供一个回调处理程序。股   提供暂停和   恢复执行线程。执行   可以在活动结束时暂停恢复   完了。这允许你写   难以读取的异步事件   处理简单,线性,可读   封装实现的代码。

答案 4 :(得分:0)

我认为你必须抓住这样的回应。我认为你不需要回电。

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

答案 5 :(得分:0)

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

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

问候DotnetShadow

答案 6 :(得分: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。

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

答案 7 :(得分: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;
}

答案 8 :(得分:0)

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