为什么这个函数是console.log的20次而不是一次?

时间:2016-09-25 19:09:46

标签: javascript ajax heroku

在application.js中,我通过ajax调用在页面上编译了所有“主题”,然后当单击一个时,所有信息都会显示在屏幕上。一切都在开发中很好,但在生产中我得到500服务器错误。

在尝试调试时,我注意到控制台正在使用.onclick调用记录20次。为什么会发生这种情况,是否有任何理由在生产中返回500错误(heroku)?

我把** **放在3个console.logs周围。

if(window.location.pathname === "/topics")  {
    $('.actions').click(function(e) {
        console.log("submit");
    })

    $.ajax({
            url: '/topics',
            dataType: 'json',
            type: 'GET',
            success: function(result)   {
                console.log(result);
                for(var i = 0; i < result.length; i++)  {
                    var title = result[i].title;
                    var level = result[i].level;
                    var id = result[i].id;
                    var favlink = '/topics/' + id + '/favorite';    
                    var link = '/topics/' + id;
                    var topicInfo = {title: title, link: link};
                    var template = compiledTopics(topicInfo);
                    $('.topic-wrapper').append(template);



                $('.listing-topics, .favorite-topic-title').click(function(e){
                        e.preventDefault();
                        if( $(this).hasClass("favorite-topic-title"))   {
                            var heartClass = "favorited_heart_icon"

                        }
                        else if( $(this).hasClass("listing-topics"))    {
                            var heartClass = "unfavorited_heart_icon";
                            $('html, body').animate({ scrollTop: 0 }, 'fast');

                        }
                        **console.log(this);**
                        $.ajax({
                            url: this,
                            dataType: "json",
                            type: 'GET',
                            success: function(result)   {


                                var id = result.id;
                                var title = result.title;
                                var body = result.body;
                                var level = result.level
                                **console.log(level);**

                                //SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED

                                //Add proper favorite icon.
                                var favlink = '/topics/' + id + '/favorite';    
                                **console.log(heartClass);**
                                var topicInfo = {title: title, body: body, heartClass: heartClass};
                                var template = compiled(topicInfo);



                                $('.topic-wrapper').append(template);

                                //CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
                                $('.topicClose').click(function(e)  {
                                    $('.topicClose').css("display", "none");
                                    $('.show_topic').css("display", "none");
                                })

                                //FAVORITE TOPIC
                                //ADD TO FAV TOPICS LIST

                                $(".unfavorited_heart_icon, .favorited_heart_icon").click(function(e)   {
                                    e.preventDefault();
                                    //onclick - change colors of heart

                                    if ( $(this).hasClass("favorited_heart_icon"))  {
                                        $(this).removeClass("favorited_heart_icon");
                                        $(this).addClass("unfavorited_heart_icon");
                                        urlEnd = '/unfavorite';
                                    }
                                    else if ( $(this). hasClass("unfavorited_heart_icon"))  {
                                        $(this).removeClass("unfavorited_heart_icon");
                                        $(this).addClass("favorited_heart_icon");
                                        urlEnd = '/favorite';
                                    }
                                    // console.log('/topics/favorite/' + id);
                                    $.ajax({
                                        url: '/topics/' + id + urlEnd,  
                                        type: 'POST',
                                        success: function(result)   {
                                            location.reload();
                                        }
                                    })

                                });



                            },
                            error: function(err)    {
                                console.log(err);
                            }


                        })
                    });


            };

        },
        error: function(err)    {

        }
    });

位于同一个js文件的底部:

var listingSource = $("#listingTopics").html();
var compiledTopics = Handlebars.compile(listingSource);

主题车把模板:

<script id="listingTopics">
  <div>
    <a href={{link}} class="listing-topics">{{title}}</a>   
  </div>
</script>

提前致谢!

编辑**

我也试过了:

$.ajax({
                url: '/topics',
                dataType: 'json',
                type: 'GET',
                success: function(result)   {
                    for(var i = 0; i < result.length; i++)  {
                        var title = result[i].title;
                        var level = result[i].level;
                        var id = result[i].id;
                        var favlink = '/topics/' + id + '/favorite';    
                        var link = '/topics/' + id;
                        var topicInfo = {title: title, link: link};
                        var template = compiledTopics(topicInfo);
                        $('.topic-wrapper').append(template).click(function(e)  {
                            e.preventDefault();
                            console.log($(this))
                        });
                };
            },

2 个答案:

答案 0 :(得分:1)

我认为通过将这些侦听器从循环中取出并使用委托策略定义它们,可以解决许多分配多个事件侦听器的问题。

我会在概念上尝试类似于:

的东西
function getTopicJSON_Success(result){
    console.log(result);

    for(var i = 0; i < result.length; i++)  {
        var title = result[i].title;
        var level = result[i].level;
        var id = result[i].id;
        var favlink = '/topics/' + id + '/favorite';    
        var link = '/topics/' + id;
        var topicInfo = { title: title, link: link };
        var template = compiledTopics(topicInfo);
        $('.topic-wrapper').append(template);
    }
}

function getJSON_Error(err){
    console.log(err);
}

if(window.location.pathname === "/topics")  {

    $('.actions').click(function(e) {
        console.log("submit");
    });

    $('.topic-wrapper').on("click", '.listing-topics, .favorite-topic-title', function(e){
        e.preventDefault();

        // =========================
        // Note at this point "this" is the element that was clicked.
        // in the ajax requrest below we will want to use $this.attr("href").
        // =========================
        console.log(this);
        // =========================

        var $this = $(this);
        var heartClass;

        if( $this.hasClass("favorite-topic-title") ) {
            heartClass = "favorited_heart_icon"
        } else if( $this.hasClass("listing-topics") ) {
            heartClass = "unfavorited_heart_icon";
            $("body").animate({ scrollTop: 0 }, 'fast');
        }

        // =========================
        // Note: could be "null".
        // Did you want one or the other specifically and not the posibility of null?
        // =========================
        console.log(heartClass);
        // =========================

        var getListJSON_Success = function(result){
            var id = result.id;
            var title = result.title;
            var body = result.body;
            var level = result.level

            console.log(level);

            //SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED

            //Add proper favorite icon.
            var favlink = '/topics/' + id + '/favorite';    
            var topicInfo = {title: title, body: body, heartClass: heartClass};
            var template = compiled(topicInfo);

            $('.topic-wrapper').append(template);

            //CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
            $('.topicClose').click(function(e)  {
                $('.topicClose').css("display", "none");
                $('.show_topic').css("display", "none");
            });

            //FAVORITE TOPIC
            //ADD TO FAV TOPICS LIST
        };

        $.ajax({
            url: $this.attr("href"),
            dataType: "json",
            type: 'GET',
            success: getListJSON_Success,
            error: getJSON_Error
        })
    });

    $('.topic-wrapper').on("click", ".unfavorited_heart_icon, .favorited_heart_icon", function(e) {
        e.preventDefault();

        var $this = $(this);
        var urlEnd;

        if ( $this.hasClass("favorited_heart_icon") ) {
            $this.removeClass("favorited_heart_icon");
            $this.addClass("unfavorited_heart_icon");
            urlEnd = '/unfavorite';
        } else if ( $this. hasClass("unfavorited_heart_icon") ) {
            $this.removeClass("unfavorited_heart_icon");
            $this.addClass("favorited_heart_icon");
            urlEnd = '/favorite';
        }

        $.ajax({
            url: '/topics/' + $this.attr("id") + urlEnd,  
            type: 'POST',
            success: function(result) { location.reload(); },
            error: getJSON_Error
        });

    });

    $.ajax({
        url: '/topics',
        dataType: 'json',
        type: 'GET',
        success: getTopicJSON_Success,
        error: getJSON_Error
    });
}

答案 1 :(得分:0)

我猜测results约有20个项目。当您在for循环中创建click事件处理程序时,将其绑定到类.listing-topics, .favorite-topic-title。单击元素时,它会继续并触发单击事件(因为结果数组中有20个项目,因此会触发20次)。我怀疑这是发生了什么,但需要看到它来验证。你有JSFiddle吗?

要解决此问题,请更改绑定事件处理程序的方式。您需要将其范围限定为类或元素的特定实例,以便事件可以单独触发而不是一次触发。

SAMPLE SCENARIO

var results = ["1", "2", "3"];


//How you're currently doing it
for (var i = 0; i < results.length; i++) {
    $('#container').append($('<div />', {text: results[i], class:'test-class'}));
  $('.test-class').click(function () {
  console.log($(this).text());
  });
}

//Solution
for (var i = 0; i < results.length; i++) {
    $('#container').append($('<div />', {text: results[i], class:'test-class'}).click(function () {
  console.log($(this).text());
  }));
}

我已经创建了这个场景的简单复制(与你的一致),以帮助更好地解释正在发生的事情。基本上,一次性(按类)绑定所有事件的instaed,在创建它时将它绑定到元素。

JSFIDDLE: https://jsfiddle.net/ncrxekmq/

更新代码

if(window.location.pathname === "/topics")  {
    $('.actions').click(function(e) {
        console.log("submit");
    })

    $.ajax({
            url: '/topics',
            dataType: 'json',
            type: 'GET',
            success: function(result)   {
                console.log(result);
                for(var i = 0; i < result.length; i++)  {
                    var title = result[i].title;
                    var level = result[i].level;
                    var id = result[i].id;
                    var favlink = '/topics/' + id + '/favorite';    
                    var link = '/topics/' + id;
                    var topicInfo = {title: title, link: link};
                    var template = compiledTopics(topicInfo);
                    $('.topic-wrapper').append(template);


                //use $.each(index, item) to loop through all of your elements and bind the click event individually instead of in one go.
                $('.listing-topics, .favorite-topic-title').each(function (index, item) {
                    $(item).click(function(e){
                        e.preventDefault();
                        if( $(this).hasClass("favorite-topic-title"))   {
                            var heartClass = "favorited_heart_icon"

                        }
                        else if( $(this).hasClass("listing-topics"))    {
                            var heartClass = "unfavorited_heart_icon";
                            $('html, body').animate({ scrollTop: 0 }, 'fast');

                        }
                        **console.log(this);**
                        $.ajax({
                            url: this,
                            dataType: "json",
                            type: 'GET',
                            success: function(result)   {


                                var id = result.id;
                                var title = result.title;
                                var body = result.body;
                                var level = result.level
                                **console.log(level);**

                                //SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED

                                //Add proper favorite icon.
                                var favlink = '/topics/' + id + '/favorite';    
                                **console.log(heartClass);**
                                var topicInfo = {title: title, body: body, heartClass: heartClass};
                                var template = compiled(topicInfo);



                                $('.topic-wrapper').append(template);

                                //CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
                                $('.topicClose').click(function(e)  {
                                    $('.topicClose').css("display", "none");
                                    $('.show_topic').css("display", "none");
                                })

                                //FAVORITE TOPIC
                                //ADD TO FAV TOPICS LIST

                                $(".unfavorited_heart_icon, .favorited_heart_icon").click(function(e)   {
                                    e.preventDefault();
                                    //onclick - change colors of heart

                                    if ( $(this).hasClass("favorited_heart_icon"))  {
                                        $(this).removeClass("favorited_heart_icon");
                                        $(this).addClass("unfavorited_heart_icon");
                                        urlEnd = '/unfavorite';
                                    }
                                    else if ( $(this). hasClass("unfavorited_heart_icon"))  {
                                        $(this).removeClass("unfavorited_heart_icon");
                                        $(this).addClass("favorited_heart_icon");
                                        urlEnd = '/favorite';
                                    }
                                    // console.log('/topics/favorite/' + id);
                                    $.ajax({
                                        url: '/topics/' + id + urlEnd,  
                                        type: 'POST',
                                        success: function(result)   {
                                            location.reload();
                                        }
                                    })

                                });



                            },
                            error: function(err)    {
                                console.log(err);
                            }


                        })
                    });
                });

            };

        },
        error: function(err)    {

        }
    });