简体   繁体   English

ajax回调中的闭包循环

[英]closure loop in ajax callback

i have a data which were parsed from json, i display the data in a box like facebook's friends suggestion box. 我有一个从json解析的数据,我在Facebook的朋友建议框中显示数据。 i want when the user click on any of the suggested users the request to be added to DB via ajax and its corresponding button disappears,everything is working just fine except the last thing(button disappears) instead the very first button in the list gets disappear, while im searching for a solution to my problem i came across something called closure but i reaaly couldn't know how to implement it in my code, another problem appeared when i tried to declare the listener anonymous function inside the loop was the data get inserted in the DB multiple times (because its inside a loop), i know it might seems duplicated question but i just need someone pointing me the right place to declare my inner function, 我希望当用户点击任何建议用户时,通过ajax将请求添加到DB并且其相应的按钮消失,一切正常,除了最后一件事(按钮消失)而不是列表中的第一个按钮消失,虽然我正在寻找我的问题的解决方案,我遇到了一些叫做闭包的东西, 我真的不知道如何在我的代码中实现它,当我试图在循环内部声明监听器匿名函数时出现另一个问题是数据获取多次插入DB(因为它在一个循环内),我知道这似乎是重复的问题,但我只需要有人指着我正确的位置来声明我的内部函数,

my code looks like this 我的代码看起来像这样

$(document).ready(function() {
    var suggest = new XMLHttpRequest();
    suggest.onreadystatechange = function() {
        if (suggest.readyState === 4 && suggest.status === 200) {
            var susers = JSON.parse(suggest.responseText);

            for (var i = 0; i < susers.length; i += 1) {
                var sphoto = '<div class="col-md-4 text-left  "> <div id="fimage">';
                sphoto += '<img  width="50" height="50" src="user/';
                sphoto += susers[i].activation + '/' + susers[i].pic + '"> </div>   </div>';
                var sname = '<div id="fname">' + susers[i].name + '</div>';

                // here is the form im targetting to pull informtion from
                var hidden = '<form id="fform"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
                hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';

                var fbutton = '<button  id="addfriend"class="btn btn-info  btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button></form';


                var display = document.getElementById('fsuggest');
                display.innerHTML += '<div class="scroller"><div id="fspace" > <button  type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' + sphoto + sname + hidden + fbutton +'</div></div>'

                $('#addfriend').live('click', function(arg) {
                    return function() {
                        arg.preventDefault();
                        var data = $('#fform').serialize();
                        $.ajax({
                            data: data,
                            type: "post",
                            url: "addnew.php",
                            success: function(data) {
                             //make the text area empty
                              $('#addfriend').css("display", "none");
                                console.log(data);
                            }

                        }); // end of $.ajax

                    }(i); // end of inner function

                }); // end of click listner 



            } //end of for loop

       }
    };

    suggest.open('GET', 'box.php');
    suggest.send();
}); // end of JQUERY ready

I am not sure why exactly you need closure here. 我不确定为什么你需要closure这里。 The problem seems to be with the multiple form & button with same id . 问题似乎是具有相同id的多个表单和按钮。

All these buttons have same id so the forms . 所有这些按钮都具有相同的id因此forms So 所以

$('#addfriend').live('click', function(arg) {..}) has no reference to the particular button 

Hope this change will help 希望这一改变会有所帮助

Con-cat the value of i with the id of the form & add an attribute data-id=i the button. 使用表单的id来表示i的值并添加属性data-id=i按钮。

Beside instead of id add class addfriend to the button. 除了id addfriend ,在按钮中添加class addfriend So when this button will be clicked take the data-id value. 因此,当单击此按钮时,请获取data-id值。 Use this value to get the relevant form with id , & serialize that 使用此值可以获取带有id的相关表单,并序列化它

var hidden = '<form id="fform_' + i + '"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';


var fbutton = '<button data-id="' + i + '" id=""class=" addfriend btn btn-info  btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>';

Make below change to the click function. 在下面更改单击功能。

Also reason of adding the event handler inside loop is not clear. 在循环中添加事件处理程序的原因也不清楚。

 $('.addfriend').live('click', function(arg) {
           arg.preventDefault();
           var getDataId = $(this).attr('data-id')  // get the data-id
            var data = $('#fform_'+getDataId).serialize(); // get relevant form
            $.ajax({
              // rest of code
           }); // end of $.ajax
           })

Try to use jquery version above 1.9 to use the on method for event delegation 尝试使用1.9以上的jquery版本来使用on方法进行事件委托

I made a few changes to your code. 我对您的代码进行了一些更改。

With the new javascript, I believe most browsers support string interpolation natively (without any extra plugins or pre-compiling with babel for example) so you can just interpolate your variables within backticks ``. 使用新的javascript,我相信大多数浏览器本身都支持字符串插值(例如,没有任何额外的插件或使用babel进行预编译),因此您可以在反引号中插入变量``。

Also, you seemed to be creating a form with the id of #fform and a button with the id of #addfriend for each iteration. 此外,您似乎与创造的ID的形式#fform与id的按钮#addfriend每个迭代。 The problem is that calling $('#fform') or $('#addfriend') will return an array with as many elements as you have users. 问题是调用$('#fform')$('#addfriend')将返回一个包含与用户一样多的元素的数组。

So I added an extra data-suser-id attribute with unique id 's on those. 所以我添加了一个额外的data-suser-id属性,其中包含唯一的id I am not sure the code will work because I can't actually try it and changed quite a few things but let me know if you are getting closer to your solution. 我不确定代码是否有效,因为我实际上无法尝试并更改了一些内容,但如果您越来越接近解决方案,请告诉我。

    $(document).ready(function() {
        var suggest = new XMLHttpRequest();
        suggest.onreadystatechange = function() {
            if (suggest.readyState === 4 && suggest.status === 200) {
                var susers = JSON.parse(suggest.responseText);
                var limit = susers.length;
                for (var i = 0; i < limit; i += 1) {
                    var sphoto = `<div class="col-md-4 text-left  ">
                                    <div id="fimage">
                                        <img  width="50" height="50" src="user/${susers[i].activation}/${susers[i].pic}">
                                    </div>
                                </div>`
                    var sname = `<div id="fname">${susers[i].name}</div>`
                    // here is the form im targetting to pull informtion from
                    var hidden     = `<form id="fform" data-suser-id='${susers[i].id}'>
                                        <input id="fnameh" name="name" type="hidden" value="${susers[i].name}" >
                                        <input name="id" type="hidden" value="${susers[i].id}">`
                    var mutalusers = `</form><div id="mutal" class="text-left">
                                        <h6>
                                            <div id="fmutal">
                                                <?php echo $c = mutal(${susers[i].id}, $me, $db) ?>
                                            </div>
                                        </h6>
                                    </div>`
                    var fbutton = `<button id="addfriend" class="btn btn-info btn-xs pull-right text-center" type="submit" data-suser-id='${susers[i].id}'>Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>`;
                    var display = document.getElementById('fsuggest');
                    display.innerHTML += `<div class="scroller">
                                            <div id="fspace">
                                                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                                                    <span aria-hidden="true">&times;</span>
                                                </button>
                                                ${sphoto}
                                                ${sname}
                                                ${hidden}
                                                ${fbutton}
                                                ${mutalusers}
                                            </div>
                                        </div>`
                        // #live method is deprecated : http://api.jquery.com/live/
                    var addfriend_button = $(`#addfriend[data-suser-id=${susers[i].id}]`)
                    addfriend_button.on('click', function(arg) {
                        // return function(){
                        arg.preventDefault();
                        // the selector `#fform` doesn't seem to be unique to the current user's form data, so I added an data-attribute to make sure we are getting the correct form data
                        var data = $(`#fform[data-suser-id=${susers[i].id}]`).serialize();
                        $.ajax({
                            data: data,
                            type: "post",
                            url: "addnew.php",
                            success: function(data) {
                                //make the text area empty for the current user's `#addfriend` button
                                addfriend_button.html('done');
                                console.log(data);
                            }
                        }); // end of $.ajax
                        // }(i); // end of inner function : not sure why this inner function is necessary
                    }); // end of click listner
                } //end of for loop
                console.log(susers);
            }
        };
        var suugestFile = 'box.php';
        suggest.open('GET', suugestFile);
        suggest.send();
    }); // end of JQUERY ready

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM