【问题标题】:Chrome doesn't displays the dynamic css propery change by Jquery before Ajax sync callChrome 在 Ajax 同步调用之前不显示 Jquery 的动态 css 属性更改
【发布时间】:2011-10-21 09:48:00
【问题描述】:

我在使用 Google Chrome 浏览器时遇到了一个棘手的问题。

我有以下 HTML 节点:

<div class="result-req-chat pointer float-right" onclick="chat.addUser(this/*, other vars*/)" ><img src="/images/profile_icon_4.png" alt="" /></div>

点击事件触发聊天对象的方法

    this.addUser = function(trigger_node, id, is_silent, session, show_block_message){
    if(trigger_node){
        this.bk_trigger_node.html = trigger_node.innerHTML;
        this.bk_trigger_node.cn = trigger_node.className;
        trigger_node.innerHTML = '';

        jQuery(trigger_node).addClass("loader");
        jQuery(trigger_node).removeClass("bpurple");
        jQuery(trigger_node).removeClass("bgray");
        jQuery(trigger_node).removeClass("button");
    }
    //alert('if this is executed then it displays the previous changes of the node');
    if(trigger_node.innerHTML == ''){
        this.addUserToChat(id, is_silent, session, show_block_message);
    }
    if(trigger_node){
        trigger_node.innerHTML = this.bk_trigger_node.html;
        trigger_node.className =this.bk_trigger_node.cn;
    }
}

addUserToChat():

    this.addUserToChat = function (id, is_silent, session, show_block_message){
    var response = this.chat_tabs.addTab(id, null);
    if(response.error){
        callUrl("/me/chat/remove-session/id/"+id);
        this.chat_tabs.removeTab(id);
        if(show_block_message) alert(response.message);
    }else{

        this.createTabsBar();
        if(!is_silent){
            this.switchTab(id);
            this.resetContainer(is_silent);
        }
        if(id == this.chat_tabs.active_tab){
            this.active_chat_obj.refresh(session);
        }

        if(this.closed){
            if(this.stop_check){
                return;
            }
            this.resetContainer();
            this.switchTab(id);
        }

    callUrl("/me/chat/add-session/id/"+id);
    }
}

chat_tabs.addTab():

    // creates and adds the a tab
this.addTab = function(id,name,user_data,session){
    var exists = this.getTab(id);
    if(!exists){

        if(session){
            var user_session_id = session.id;
            var user_session_data = session.data;
        }else{
            var session = this.createSession(id);
            if(session.error){
                return session;
            }
            var user_session_id = session.id;
            var user_session_data = session.data;
        }
        if(name){
            var user_name = name;
        }else{
            var user_name = this.getName(id);
        }
        if(user_data){
            var user_data = user_data;
        }else{
            var user_data = this.getData(id);
        }

        var ob = new Object({
            user_id: id,
            user_name: user_name,
            user_data: user_data,
            user_session_id: user_session_id,
            user_session_data: user_session_data,
            has_new:false,
            chat_screen: new ChatScreen(session, id, user_name, user_data, this.main_user_id, this.main_user_photo)
            });

        this.chat_users.push(ob);
        return ob;
    }else{
        return exists;
    }
}

callUrl():

    function getUrl(url){
return jQuery.ajax({ type: 'GET', url: url, async: false }).responseText;

}

关键是addUserToChat() 方法包含一个同步Ajax 调用。

Chrome 的问题是 trigger_node 更改不显示。如果您使用内置的 JS 调试器观看,那么一切正常(即使显示)。此外,如果您取消注释警报。

它在 Mozilla(最新版本)上运行。Crome 也是最新版本。 我可以观察到,在它等待 ajax 响应时,页面对悬停、提示等事件没有响应。

您对此有什么建议吗?我怎样才能实现一个workarround方法?

【问题讨论】:

    标签: javascript css ajax google-chrome


    【解决方案1】:

    同步 Ajax 调用是不好的做法!他们在整个持续时间内停止浏览器并欺骗用户认为某些东西崩溃了。你真的应该改变它。

    关于您为什么看不到最新的 DOM 更改的问题:

    当您在 JavaScript 中更改某些内容时,浏览器不会立即更改 DOM,因为绘制一个 ui 元素比绘制一打要昂贵得多。所以现代浏览器会尽量懒惰地改变 DOM。

    除了性能之外还有其他好处,比如

    $('p').hide();
    

    可以同时隐藏所有 p 元素,尽管 jQuery 会选择每个元素而不是更改 css。

    如果不更好地理解您的代码,我无法为您提供任何解决方法,抱歉。谢谢!

    更新:

    阅读您的代码后,我会考虑为应用程序添加一些闭包。 javascript 的一个基本概念是函数是第一类类型。我个人认为,您的程序流程不太理想,这是需要改进的地方。调用 url 的调用应如下所示:

    var callUrl = function(url, callback, interactionStoped) {
       if(typeof interactionStoped != 'undefined' && interactionStoped == true) {
           //add code to display some loading animation
       }
    
       jQuery.ajax({ type: 'GET', url: url, success: function(data) {
           callback(data);
           //remove loading animation here
       } });
    }
    

    作为一个开始。然后重构您的 getUrl 调用。

    • 有趣的是,在您的代码示例中,您从不使用响应,所以我不知道您的应用正在等待什么。假设它很重要,您必须始终在回调中处理响应。
    • 尝试将您的应用视为一棵树。父函数或对象将称自己为一些处理不同任务的子函数,它们自己将调用其他函数。构建小型的方法,并且只对非常小的数据/参数集执行一件事。

    我无法重写您的完整代码,但我希望这对您有所帮助。

    【讨论】:

    • 我使用的是同步 Ajax,因为我需要一个变量中的响应,但我没有找到一种优雅的异步方式。所以我经常使用这个:function getUrl(url){ return jQuery.ajax({ type: 'GET', url: url, async: false }).responseText; }
    • 请更改您的问题并添加执行此操作的代码。
    【解决方案2】:

    您何时尝试显示/填充trigger_node 变量?

    您似乎没有在 AJAX 请求的回调函数中执行此操作。请注意,如果在您尝试检查 trigger_node 时请求仍在运行,它当然不会显示您的更改。

    【讨论】:

    • 这是一个同步请求,它只会持有浏览器。
    • 我想在警报之前查看更改,然后我需要执行代码(将用户添加到聊天中),然后恢复以前的更改(使用 this.bg_trigger_node obj) .思路是把用户点击的HTML元素替换成加载动画,加载完成后恢复点击的元素。
    • 我知道它拥有浏览器,但我对 trigger_node 元素的更改是在此之前进行的。那么显示这些更改并在此之后保留浏览器是不对的吗?谢谢!
    • 响应对另一个答案所做的评论(关于您需要变量中的响应的主题)。响应保存在 XHR-Object 中,因此您可以在请求完成后访问它。所以我真的不明白你的问题。介意您是否进一步调查您的问题?
    • @SerbuFlorin-Adrian:不!看看我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多