Ajax呼叫" for"循环跳过奇数/偶数迭代

时间:2016-04-18 18:31:33

标签: javascript jquery ajax asynchronous callback

如果我在这里问这是因为我们陷入了一些我们不知道如何解决的问题。我必须承认,我们已经在StackOverflow和搜索引擎中搜索了一个解决方案..但我们没有设法实现它/解决问题。

我正在尝试创建一个JavaScript函数:

  • 在我的html页面中检测到所有html标记:<alias>

  • 将其内容替换为Ajax调用的结果(发送 标签的内容到Ajax.php页面)+ localStorage管理

  • 最后将其从<alias>标记中解包并保留从ajax调用返回的内容

唯一的问题是,在这两种情况下都会跳过一些迭代。 我们已经做了一些研究,似乎&#34;问题&#34;是 Ajax是异步的,所以在继续进程之前它不会等待响应。我们甚至看到了&#34; async:false&#34;不是一个好的解决方案。

我留下了对一些简短描述感兴趣的脚本部分

// includes an icon in the page to display the correct change
    function multilingual(msg,i) {
         // code  
    }

    // function to make an ajax call or a "cache call" if value is in localStorage for a variable
    function sendRequest(o) {
        console.log(o.variab+': running sendRequest function');
        // check if value for that variable is stored and if stored for more than 1 hour
        if(window.localStorage && window.localStorage.getItem(o.variab) && window.localStorage.getItem(o.variab+'_exp') > +new Date - 60*60*1000) {
            console.log(o.variab+': value from localStorage');
            // replace <alias> content with cached value
            var cached = window.localStorage.getItem(o.variab);
            elements[o.counter].innerHTML = cached;

            // including icon for multilingual post
            console.log(o.variab+': calling multilingual function');
            multilingual(window.localStorage.getItem(o.variab),o.counter);

        } else {
            console.log(o.variab+': starting ajax call');
            // not stored yet or older than a month
            console.log('variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language);
            $.ajax({
                type: 'POST',
                url: my_ajax_url,
                data: 'variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language,
                success: function(msg){
                    // ajax call, storing new value and expiration + replace <alias> inner html with new value
                    window.localStorage.setItem(o.variab, msg);
                    var content = window.localStorage.getItem(o.variab);
                    window.localStorage.setItem(o.variab+'_exp', +new Date);
                    console.log(o.variab+': replacement from ajax call');
                    elements[o.counter].innerHTML = content;

                    // including icon for multilingual post
                    console.log(o.variab+': calling multilingual function');
                    multilingual(msg,o.counter);
                },
                error: function(msg){
                    console.warn('an error occured during ajax call');
                }
            });
        }
    };

    // loop for each <alias> element found
        //initial settings
            var elements = document.body.getElementsByTagName('alias'),
            elem_n = elements.length,
            counter = 0;
            var i = 0;

    for(; i < elem_n;i++) {
        var flag = 0;
        console.info('var i='+i+' - Now working on '+elements[i].innerHTML);
        sendRequest({
            variab : elements[i].innerHTML,
            api_key : settings.api_key,
            language : default_lang,
            counter : i
        });

        $(elements[i]).contents().unwrap().parent();
        console.log(elements[i].innerHTML+': wrap removed');
    }

我希望你们中的一些人可以为我提供一些有效的解决方案和/或例子,因为我们坚持这个问题:(

从我们的测试中,当值来自缓存时,第1 /第3 /第5 ...值被正确替换 当值来自ajax时,第二个/第四个..值被替换

提前感谢您的帮助:)

2 个答案:

答案 0 :(得分:4)

您的elements数组是实时 NodeList。当您打开那些<alias>标签中的内容时,该元素将从列表中消失。所以,你正在查看元素0,然后进行ajax调用,然后你摆脱了内容周围的<alias>标记。在那一刻,element[0]成为使用element[1]。但是,您的循环会增加i,因此您会跳过新的element[0]

无论如何都没有理由使用.getElementsByTagName();你正在使用jQuery,所以要始终如一地使用它:

var elements = $("alias");

这会给你一个jQuery对象,它(大部分)就像一个数组一样工作,所以你的代码的其余部分不需要改变很多,如果有的话。

答案 1 :(得分:0)

为了解决过去这样的问题,我做了类似下面的代码,你实际上发送了目标以及运行AJAX调用的函数,并且不使用任何全局变量,因为它们可能会随着for循环运行。尝试传递你将在函数参数中使用的所有内容,包括我已完成的目标:

function loadContent(target, info) {
    //ajax call
    //on success replace target with new data;
}
$('alias').each(function(){
    loadContent($(this), info)
});