代码之家  ›  专栏  ›  技术社区  ›  Kristen D.

在safari/chrome中完成Ajax调用之前,加载动画不会显示。

  •  1
  • Kristen D.  · 技术社区  · 15 年前

    我遇到了一个我还没找到解决办法的问题。

    我正在创建一个资源预订应用程序,它使用Ajax将用户提供的信息处理到后端数据库中。每当用户想要创建预订时,他们都会填写一个表单,其中包含通过Ajax发送给servlet的相关信息,servlet处理信息并更新数据库。因为我们包含了预订重复选项,有时数据库需要一段时间才能更新。因此,我们实现了一个“处理…”图形,当servlet完成它的事情时显示出来。

    我们实现处理图形和Ajax调用的方式在Firefox、Opera和IE中运行良好,问题在于Safari和Chrome…所以可能和WebKit有关。

    在safari/chrome中,在数据库完成工作并返回Ajax调用之前,处理图形不会显示在页面上…破坏了“处理…”图形的全部目的。

    有人知道为什么图形(在调用Ajax请求之前插入)直到Ajax调用返回后才显示吗?

    下面是我们如何实现图形和Ajax调用。这是一个调用函数来创建图形和发送Ajax请求的函数:

    /**
     * Implements AJAX calls to add/remove bookings from the database
     */
    function processBooking(selection, responseID, formElement, removing, fromManager, resourceType) {
    
     if (!removing) {
     purpose = formElement.purpose.value;
     email = formElement.email.value;
    
                /* These values should only be set if the user is an admin otherwise they do not exist so send in the default empty
                 * values to the processing servlet
                 */
                if (formElement.repeatEveryUnits != undefined && formElement.repeatFor != undefined && formElement.repeatForUnits != undefined)
                {
                    repeatEvery = formElement.repeatEveryUnits.value;
                    repeatForAmount = formElement.repeatFor.value;
                    if (repeatForAmount == '') {
                            repeatForAmount = '0';
                    }
                    repeatForUnit = formElement.repeatForUnits.value;
                }
                else
                {
                    repeatEvery = '0';
                    repeatForAmount = '0';
                    repeatForUnit = '0';
                }
    
     }
    
        /* Function to be passed in as the callback to our asynchronous request */
        callback = function() {
            document.getElementById(responseID).innerHTML += '<p class="button-small" onclick="removeDiv(\'' + responseID + '\')>Clear</p>';
            document.getElementById(responseID).style.padding = '0 0 5px 0';
        }
    
        /* Parameters that are to be used in our asynchronous request */
        postData += parseArray(selection);
        postData += '&removing=' + removing;
        postData += '&availability=false';
        postData += '&type=' + resourceType;
    
        /* Play the loading graphic */
        startLoading();
    
        /* Make the call to the servlet */
        response = sendAsyncRequest(url,postData,callback,false);
    
        /* reset global variables used */
        reset();
    
        if ((!removing) || (!fromManager))
        {
            week = document.getElementById("selectedWeek").value;
    
            window.location = "../../servlet/ResourceBooking?action=schedule&type=" + resourceType + "&week=" + week;
        }
    
        return response;
     }
    

    这是插入图形的代码:

    /**
     *      Begins a loading animation that is to be played while the database does its work 
     */
    function startLoading() {
    
        document.getElementById("container").style.opacity = "0.2";
        document.getElementById("cover").style.display = "block";
        var newDiv = document.createElement("div");
    
        newDiv.setAttribute("id", "loading");
        newDiv.style.height = 120 + "px";
        newDiv.style.width = 350 + "px";
    
        newDiv.innerHTML = "<div id='progress'><p id='progress'><img id='progress_image' src='/intranet/images/ajax-loader.gif' alt=''><br/><h3>Processing database...</h3></p></div>";
        document.body.appendChild(newDiv);
    
        ignoreClicks = true;
     }
    

    这是使xmlhttpRequest用于Ajax调用的代码:

    function sendAsyncRequest(servletUrl, postData, callback, async) {
    
    try {
          asyncRequest = new XMLHttpRequest();
    }
    catch (e) {
            // Internet Explorer Browsers
            try {
                    asyncRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
                    try {
                    asyncRequest = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch(e){
                            // Something went wrong
                            alert('Request Failed');
                            return false;
                    }
            }
    }
    
    asyncRequest.onreadystatechange = function() {
        if (asyncRequest.readyState == 4 && asyncRequest.status == 200) {
                    try {
                                    callback();
                    }
                    catch (e) {
                             // IE fails unless we wrap the string in another element.
                            var childDiv = current_element.getElementsByTagName("div");
                            if (childDiv.length == 0) {
                                    var wrappingDiv = document.createElement('div');
                                    //wrappingDiv.setAttribute("id", current_element.id+"Div");
                                    wrappingDiv.innerHTML = asyncRequest.responseText;
                                    current_element.appendChild(wrappingDiv);
                            }
                            else {
                                    var wrappingDiv = document.createElement('div');
                                    //wrappingDiv.setAttribute("id", current_element.id+"Div");
                                    wrappingDiv.innerHTML = asyncRequest.responseText;
                                    current_element.replaceChild(childDiv[0], wrappingDiv);
                                    //childDiv[0].innerHTML = asyncRequest.responseText;
                            }
                    }
            }
    };
    
    asyncRequest.open('POST', servletUrl, async);
    
    if (postData == null)
    {
        asyncRequest.send(null);
    }
    else
    {
        asyncRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        asyncRequest.setRequestHeader("Content-length", postData.length);
        asyncRequest.setRequestHeader("Connection", "close");
        asyncRequest.send(postData);
    }
    
    return response;
    }
    

    webkit有没有什么东西可以防止在发出请求之前将startloading div动态添加到页面中?

    我尝试在加载图形后对请求本身(sendAsyncRequest(…)进行注释,图形看起来会非常好,所以当我们跟踪请求时,它似乎发生了什么事情。

    感谢你的帮助,我很茫然…

    克里斯汀

    2 回复  |  直到 13 年前
        1
  •  2
  •   Alexis Pigeon Shawn Skelton    13 年前

    这是一条旧线,但就在今天我也遇到了类似的问题。也许它能帮助别人:)。

    我在IE中也遇到了类似的问题——我有自己的加载类型DIV,它在Ajax请求之前显示,在数据加载之后隐藏。我的DIV只在数据加载后显示了一段时间(只是闪烁)。

    像这样:

    document.getElementById('pnLoaderPanel').style.display = 'block';
    Task.Refresh(); //method that calls ajax
    document.getElementById('pnLoaderPanel').style.display = 'none';
    

    所以我注意到,如果在显示DIV后立即发出警报,我的DIV就可见了。我想我不知怎么地没有正确地刷新,所以我做的是这个,现在它工作得很好:

    document.getElementById('pnLoaderPanel').style.display = 'block';
    setTimeout(Task.Refresh(), 1); //method that calls ajax
    document.getElementById('pnLoaderPanel').style.display = 'none';
    
        2
  •  0
  •   pixl coder    15 年前

    您可以为图像加载事件设置回调,然后仅在加载Ajax Post时执行它。就像这样…

    function processBooking(selection, responseID, formElement, removing, fromManager, resourceType) {
        //...some stuff
        startLoading(function(){
            sendAsyncRequest(url,postData,callback,false);
        });
        //...some more stuff
    }
    
    function startLoading(callback) {
        document.getElementById("container").style.opacity = "0.2";
        document.getElementById("cover").style.display = "block";
        var img = new Image();
        img.onload=callback;
        img.src="/intranet/images/ajax-loader.gif";
        var newDiv = document.createElement("div");
    
        newDiv.setAttribute("id", "loading");
        newDiv.style.height = 120 + "px";
        newDiv.style.width = 350 + "px";
    
        newDiv.innerHTML = "<div id='progress'><p id='progress'><img id='progress_image'     src='/intranet/images/ajax-loader.gif' alt=''><br/><h3>Processing database...</h3></p>     </div>";
        document.body.appendChild(newDiv);
    
        ignoreClicks = true;
     }