每次a4j AJAX响应后如何调用JavaScript函数?

4
我正在使用JSF w/Seam开发一个Web应用程序。我想在每次ajax响应后调用一个JavaScript函数。我希望找到一种方法,在每个页面的每个commandLink/commandButton上不添加oncomplete属性的情况下实现这一点。
我认为可以设置一个servlet过滤器(拦截器?我对这些术语感到困惑),将JS调用注入到每个响应中。我会研究一下这个方法。同时,如果有人有其他建议,我很乐意听取。
编辑:我认为jQuery ajaxSuccess方法可能是解决这个问题的方法,但我不知道如何实际使用它。我无法注册任何东西。我基本上想添加代码来获取任何来源的所有ajax请求,在成功时调用我的JavaScript方法。有人能展示一下正确的做法吗?我尝试了许多种方法,包括将jQuery("*").ajaxSuccess(function(){myFunction();});添加到我的模板xhtml文件底部。
4个回答

5

重写后的回答: 查看修订历史中的原始回答

您可以通过覆盖默认的XMLHttpRequestsend方法,并劫持readystatechange处理程序来实现:

(function () 
{ 
    var xhrSend = XMLHttpRequest.prototype.send; 
    XMLHttpRequest.prototype.send = function  () 
     { 
        var handler = this.onreadystatechange; 
        this.onreadystatechange = function () 
        { 
            if (handler) {
                if (handler.handleEvent) handler.handleEvent.apply(xhr, arguments);
                else handler.apply(xhr, arguments);
            }
            if (this.readyState == 4) 
            { 
                // your oncomplete function here 
                this.onreadystatechange = handler; 
             } 
         }; 
        xhrSend.apply(this, arguments); 
    }; 
})(); 

编辑:上面的函数不能与jQuery请求一起使用,因此可能也会在其他库中失败。下面的修订通过使用setTimeout技巧来延迟覆盖处理程序的代码来解决了这个问题。当然,对于jQuery,您可以使用.ajaxSuccess()全局处理程序,但对于具有类似行为的其他库,这将非常有用。

(function() {
    function globalHandler() {
        if (this.readyState == 4) {
            // your oncomplete code here
        }
    }
    var xhrSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function() {
        var xhr = this;
        if (xhr.addEventListener) {
            xhr.removeEventListener("readystatechange", globalHandler);
            xhr.addEventListener("readystatechange", globalHandler, false);
        }
        else {
            function readyStateChange() {
                if (handler) {
                    if (handler.handleEvent)
                        handler.handleEvent.apply(xhr, arguments);
                    else
                        handler.apply(xhr, arguments);
                }
                globalHandler.apply(xhr, arguments);
                setReadyStateChange();
            }
            function setReadyStateChange() {
                setTimeout(function() {
                    if (xhr.onreadystatechange != readyStateChange) {
                        handler = xhr.onreadystatechange;
                        xhr.onreadystatechange = readyStateChange;
                    }
                }, 1);
            }
            var handler;
            setReadyStateChange();
        }
        xhrSend.apply(xhr, arguments);
    };
})();

点击链接,这是一个测试代码,我已经在IE7-9、Chrome和FF最新版本中进行了测试。


我也尝试过了,但仍然没有效果。问题可能是我的ajax请求不是通过jQuery完成的吗? - iandisme
@iandisme - 是的!! 绝对没错! 这就是你的问题。.ajaxSuccess是一个jQuery事件。如果你在jQuery之外进行常规的XMLHttpRequest,那么jQuery就无法知道它。 - gilly3
@iandisme - 我认为Martin的答案可能是你最好的解决方案,因为你正在使用a4j进行AJAX请求。但是,如果你无法让它工作,请看看我在这里重新编写的答案。 - gilly3
我给你点赞是因为这段代码非常棒。紧接着内置对象的原型,这样写很不错。但不幸的是,加入这段代码后,所有我的ajax请求都失败了。 - iandisme
如果您继续更改答案并添加.handleEvent部分,我将接受您的答案并授予悬赏。这样其他人也可以从您的帮助中受益。 - iandisme
显示剩余4条评论

3
由于您正在使用RichFaces,您可以简单地使用以下内容:
<a:status id="globalStatus" onstart="onRequestStart()" onstop="onRequestEnd()" />

这对我不起作用。根据文档,有一个“for”属性指向我需要指定的a4j输出区域。但是,仅将其添加到我的模板文档中的主表单并没有起作用。感谢介绍那个标签。 - iandisme
仅凭记忆而言:我认为这对我有用是因为我们定义了全局的ajax队列。如果您有这样的队列,则应该可以使用此方法。否则,您可以在“for”属性中定义队列名称,例如也可以使用Ajax按钮的id。我建议查看Richfaces的在线演示以获得更多信息。 - Martin Frey
我使用全局ajax队列来避免著名的并发调用对话问题,所以既然您还没有定义一个,我想知道您是否不使用对话或以不同的方式解决了它? - Martin Frey

2
使用a4j:status应该可以实现,但必须放在h:form标签内:
<h:form id="randomForm" styleClass="edit">
        <a:status id="stateStatus"
         onstart="Richfaces.showModalPanel('waitBx'),document.getElementById('randomForm:search').disabled=true;"
         onstop="Richfaces.hideModalPanel('waitBx'),document.getElementById('randomForm:search').disabled=false;"
        styleClass="message" >
</a:status>

...... way more code  
</form> 

每次Ajax调用后,会弹出一个等待图片并禁用搜索按钮。 有趣的是,在我们的代码中,这对于嵌套在a4j:region中的任何内容都不起作用。

1

这个也无法工作。jQuery("*").bind("ajaxSuccess", function(){myFunction();}); 还有很多其他的东西根本就不起作用。 - iandisme
链接无法使用(至少在今天[2013年7月10日]该网站不可用)。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接