【问题标题】:How to slow down an Ajax call?如何减慢 Ajax 调用?
【发布时间】:2016-09-20 18:35:28
【问题描述】:

我在 JS 中有一个函数包含一个循环,每次迭代都会调用一个 AJAX 调用。调用将checked 元素插入数据库,并在下一节的同一页面中返回这些元素的结果。

我遇到的问题是,当我检查例如3 个组中的 4 个复选框,最后一组的唯一复选框被添加到页面。但是,当我使用alert() 时,我可以看到所有元素。

我使用了 setTimeout,但在代码中出现错误。我还添加了一些行来为 AJX 调用提供更多时间,但问题仍然存在。所以我想知道是否有一个解决方案可以在不使用alert()的情况下减慢代码。

这是我的脚本:

addAptitudeField : function(currentAutocompleteField, idChamp) {

    var currentAutocompleteFieldBind = currentAutocompleteField;
    var idChampBind = idChamp;

    window.setTimeout(function() {

        // Code ...

        var paramDwr = {};
        var newDivName = "div" + idChamp + lastValueId;
        paramDwr[attributs.r_divId] = newDivName;
        paramDwr[attributs.r_currentValue] = currentValue;
        paramDwr[attributs.r_hiddenIdsField] = hiddenIdsField.id;
        paramDwr[attributs.r_lastValueId] = lastValueId;
        paramDwr[attributs.r_itemmod] = nbAptitudesCat % 2 == 0;

        // setTimeout ( RepertoireDwr.ligneSuppEtSpanMessage, 1000 ) doesn't work

        RepertoireDwr.ligneSuppEtSpanMessage(paramDwr, function(ajaxPage) {
            divCategorie.update(divCategorie.innerHTML + ajaxPage.texte);
            aptitudeAvecDetail.remetsValeursStockees();
            var btnSuppression = $(newDivName).getElementsByTagName('img')[0];
            btnSuppression.setAttribute("onclick", "formulaireFiche.updateCSS('" + newDivName + "');" + btnSuppression.getAttribute("onclick") + "fiche.updateCategorieSuppressionAptLieeUo(\'divCat" + currentCategorie + "\');"); });
            }
        //
        // alert() : It works in this case.
        //

        // for (var i=0; i<5000000; i++) ; it doesn't work

        }, 400);
    }

提前感谢您的帮助和时间。

【问题讨论】:

  • 什么循环?它是如何“不工作”的?你遇到了什么错误?真的不清楚你在问什么,但听起来你肯定是在尝试通过创建不同的问题来解决问题。
  • 我已将您的问题挽救为我认为您的意思。请查看我的更正
  • 非常感谢@Martijn,是的,这正是我所要求的,我为我的语言感到抱歉。
  • @David 嗯,通常,前面的函数“addAptitudeField”允许按时间处理一个元素,所以我创建了一个调用这个函数的函数:additems : function () { var nbritem = $('selector').length; for (var i = 0; i &lt; nbritem ; i++) addAptitudeField($('selector').[i]); } 就是这样,我每次调用都一样具有特定元素 id 的函数
  • 你应该看看 promises。

标签: javascript jquery ajax


【解决方案1】:

您遇到的问题与异步函数或 AJAX 中的 A 有关。如果你不知道什么是异步函数,还有很多人比我能解释得更好,所以给个谷歌吧。

如果没有 alert() 会发生什么情况,您的代码会进行 4 次服务器调用,但在您得到任何响应之前,所有 4 次都已发送出去。使用alert()(或setTimeout),您可以在发出下一个呼叫之前给代码时间来接收对呼叫的每个响应。

有几种方法可以解决这个问题,第一种方法是在第一个调用收到响应后调用下一个调用。第二种方法是使用异步函数在不同的链上一次调用所有 4 个(?)。我不是最擅长解释这部分的,但是在 SO 和在线上可以找到很多代码。

【讨论】:

  • 是的,这正是我想要做的,是在第一次收到响应后继续下一次调用,通过使用 setTimeout 和许多指令给 Ajax 时间,但没有好的结果.顺便谢谢你
【解决方案2】:

我认为您的代码中存在更普遍的问题,因为您似乎需要延迟执行以等到某事。 else 已完成,而不是在完成时通知。

最让我烦恼的就是这一句

divCategorie.update(divCategorie.innerHTML + ajaxPage.texte);

更新到底在做什么?它是如何实施的? 我认为它会做某事。喜欢divCategorie.innerHTML += ajaxPage.texte;
Wich 非常不利,因为浏览器必须解析和重建,无论divCategorie.innerHTML 中已经存在什么。

只附加新的标记会更好。

很长的路要走:也许一个很好的技巧是插入一些隐藏节点作为占位符(这样你就可以保持顺序,尽管 AJAX 请求可能以不同的顺序返回)并用真实内容替换该节点,如很快就到了。

有点像这样:

addAptitudeField : function(currentAutocompleteField, idChamp) {

    var currentAutocompleteFieldBind = currentAutocompleteField;
    var idChampBind = idChamp;

    //this is done immediately, and therefore preserves the order of the loop, 
    //without any delays/timeouts
    var placeholder = document.createElement("div");
        placeholder.className = "placeholder";
        placeholder.style.display = "none";
    divCategorie.appendChild(placeholder);

    window.setTimeout(function() {

        // Code ...

        var paramDwr = {};
        var newDivName = "div" + idChamp + lastValueId;
        paramDwr[attributs.r_divId] = newDivName;
        paramDwr[attributs.r_currentValue] = currentValue;
        paramDwr[attributs.r_hiddenIdsField] = hiddenIdsField.id;
        paramDwr[attributs.r_lastValueId] = lastValueId;
        paramDwr[attributs.r_itemmod] = nbAptitudesCat % 2 == 0;

        // setTimeout ( RepertoireDwr.ligneSuppEtSpanMessage, 1000 ) doesn't work

        RepertoireDwr.ligneSuppEtSpanMessage(paramDwr, function(ajaxPage) {
            //convert the passed text into a DocumentFragment
            var frag = fragment(ajaxPage.texte);

            //replacing the placeholder with the fragment
            divCategorie.insertBefore(frag, placeholder);
            divCategorie.removeChild(placeholder);

            aptitudeAvecDetail.remetsValeursStockees();
            var btnSuppression = $(newDivName).getElementsByTagName('img')[0];
            //this is also pretty horrible to me:
            btnSuppression.setAttribute("onclick", "formulaireFiche.updateCSS('" + newDivName + "');" + btnSuppression.getAttribute("onclick") + "fiche.updateCategorieSuppressionAptLieeUo(\'divCat" + currentCategorie + "\');"); });
            }
        }, 400);
    }

我认为您应该进行一些重大的重构。并查看 Promises。

// * -> DocumentFragment
//strings/primitives are parsed as HTML-markup, 
//null / undefined is ignored
//Arraylike structures are parsed recursively
var fragment = (function(container){
    return function(src){
        return reducer(document.createDocumentFragment(), src);
    }

    function reducer(frag, node){
        var i, len, fc, c, r;
        if(node === Object(node)){
            if("nodeType" in node){
                //dom nodes
                frag.appendChild(node);
            }else{
                //Arraylike structures, like NodeLists or jQuery-Objects, or just plain Arrays
                for(i = 0, len = ("length" in node && node.length)|0, r = reducer; i < len; (i in node) && r(frag, node[i]));
            }
        }else if(node != null) {
            //strings (all primitives)
            for((c=container).innerHTML = node; fc = c.firstChild; frag.appendChild(fc));
        }
        return frag;
    }
})(document.createElement("div"));

【讨论】:

  • 感谢您的回复,首先,更新功能允许显示已添加到字段中的类别,因此每次添加新类别时,此功能都会将其插入到旧列表中。我承认代码不清楚,它对我来说既旧又复杂(我是 JS 的初学者)。我将尝试使用您的代码,看看我能用它做什么。再次感谢您。
【解决方案3】:

我可能会因为提到这一点而被否决,因为这不是推荐的程序,但我相信每个编码人员都应该掌握所有事实。

在 jQuery AJAX 构造中,有一个选项 async:false, 将延迟脚本继续执行,直到 AJAX 完成处理。不用说,如果 AJAX 出现问题,浏览器可能会死机。 很大程度上取决于你的用户是谁,以及流量——在我的十个用户内部项目中,这是一个可以接受的解决方案。

$.ajax({
    async: false,
    type: 'post',
     url: 'ajax/ax.php',
    data: 'request=',
    success: function(d){
        if (d.length) alert(d);
    }
});

参考:

What does "async: false" do in jQuery.ajax()?


不过,更好的办法是查看 Promises 接口,使用 .when().then() 等方法

参考资料:

https://jsfiddle.net/v86bc028/2/

http://jqfundamentals.com/chapter/ajax-deferreds#

http://digitizor.com/jquery-html-callback-function-using-promise/#

how does jquery's promise method really work?

【讨论】:

  • 它工作知道,我把 async 设置为 false 并且它工作得很好,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 2013-04-04
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2021-05-01
  • 2018-06-04
相关资源
最近更新 更多