You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript 点赞/点踩计数器逻辑错误排查与修复记录

点赞/点踩计数器Bug修复记录

已修复该Bug并做代码记录,方便后续参考。之前开发点赞/点踩计数器时碰到逻辑错误:脚本原本要实现点击按钮可点赞/点踩或取消操作,且点赞后点踩(或反之)时对应计数器正常增减,但连续点击两个按钮后,其中一个计数器会被重置为0。

原问题代码

<script type="text/javascript">
    var dislike_b = like_b = false;

    var num1 = 0;
    var like = parseInt("{{post.like_votes}}");

    var num2 = 0;
    var dislike = parseInt("{{post.dislike_votes}}");

    function likeHandler() {
        const xhr = new XMLHttpRequest();

        if (dislike_b == true){
            dislikeHandler();
            //dislike_b = false ;
        }
        
        // like iterator
        like = like + (-1)**num1 ;
        num1 = (num1 + 1)%2;
        document.getElementById("like").innerHTML = like;
        like_b = !like_b;

        console.log( like , num1);

        $.ajax(
            {
                type: "POST",
                url: "/likepost/",
                data: {
                    votes : like ,
                    csrfmiddlewaretoken: '{{ csrf_token }}'
                },
                success: function (data) {
                    $('#message').text(data);
                }
            })
        

    }

    function dislikeHandler() {
        const xhr2 = new XMLHttpRequest();

        if (like_b == true){
            likeHandler();
        }
        
        // like iterator
        dislike = dislike + (-1)**num2 ;
        num2 = (num2 + 1)%2;
        document.getElementById("dislike").innerHTML = dislike;
        dislike_b = !dislike_b;

        console.log( dislike , num1);

        $.ajax(
            {
                type: "POST",
                url: "/dislikepost/",
                data: {
                    votes : dislike ,
                    csrfmiddlewaretoken: '{{ csrf_token }}'
                },
                success: function (data) {
                    $('#message').text(data);
                }
            })
        

    }
</script>

问题分析

  1. 递归调用引发状态混乱:当用户已点踩后点击点赞,likeHandler会调用dislikeHandler,而dislikeHandler若检测到点赞状态又会回调likeHandler,导致状态被多次无规则修改,计数器计算逻辑彻底混乱。
  2. 计数依赖的中间变量未重置:切换点赞/点踩时,对方操作依赖的num1/num2未被重置,后续再次操作时会基于错误的中间值计算,导致计数器异常重置。
  3. 状态标志更新时机错误:调用对方handler后才更新自身状态标志,逻辑判断的时序出现偏差,进一步加剧状态混乱。

修复后的代码

<script type="text/javascript">
    let isLiked = false;
    let isDisliked = false;

    let likeCount = parseInt("{{post.like_votes}}");
    let dislikeCount = parseInt("{{post.dislike_votes}}");

    // 抽离DOM更新逻辑
    function updateLikeDisplay() {
        document.getElementById("like").innerHTML = likeCount;
    }

    function updateDislikeDisplay() {
        document.getElementById("dislike").innerHTML = dislikeCount;
    }

    function likeHandler() {
        // 若当前有点踩状态,先取消点踩
        if (isDisliked) {
            dislikeCount++;
            isDisliked = false;
            updateDislikeDisplay();
            // 发送取消点踩请求
            $.ajax({
                type: "POST",
                url: "/dislikepost/",
                data: {
                    votes: dislikeCount,
                    csrfmiddlewaretoken: '{{ csrf_token }}'
                },
                success: function (data) {
                    $('#message').text(data);
                }
            });
        }

        // 处理当前点赞操作:取消/添加
        if (isLiked) {
            likeCount--;
            isLiked = false;
        } else {
            likeCount++;
            isLiked = true;
        }
        updateLikeDisplay();

        // 发送点赞请求
        $.ajax({
            type: "POST",
            url: "/likepost/",
            data: {
                votes: likeCount,
                csrfmiddlewaretoken: '{{ csrf_token }}'
            },
            success: function (data) {
                $('#message').text(data);
            }
        });
    }

    function dislikeHandler() {
        // 若当前有点赞状态,先取消点赞
        if (isLiked) {
            likeCount++;
            isLiked = false;
            updateLikeDisplay();
            // 发送取消点赞请求
            $.ajax({
                type: "POST",
                url: "/likepost/",
                data: {
                    votes: likeCount,
                    csrfmiddlewaretoken: '{{ csrf_token }}'
                },
                success: function (data) {
                    $('#message').text(data);
                }
            });
        }

        // 处理当前点踩操作:取消/添加
        if (isDisliked) {
            dislikeCount--;
            isDisliked = false;
        } else {
            dislikeCount++;
            isDisliked = true;
        }
        updateDislikeDisplay();

        // 发送点踩请求
        $.ajax({
            type: "POST",
            url: "/dislikepost/",
            data: {
                votes: dislikeCount,
                csrfmiddlewaretoken: '{{ csrf_token }}'
            },
            success: function (data) {
                $('#message').text(data);
            }
        });
    }
</script>

修复说明

  1. 移除递归调用:不再通过调用对方handler处理切换,直接在当前函数内完成对方状态的清理,避免状态混乱。
  2. 简化状态管理:用isLiked/isDisliked清晰标记当前状态,替代原有的模糊变量命名,逻辑更直观。
  3. 重构计数逻辑:直接通过增减操作更新计数器,去掉易混淆的num1/num2中间变量,彻底避免计数重置错误。
  4. 拆分DOM更新:把显示更新逻辑抽成独立函数,代码结构更整洁,便于后续维护。
  5. 明确操作顺序:切换操作时先处理对立状态的清理,再执行当前操作,确保数据和状态的一致性。

内容的提问来源于stack exchange,提问作者Shaswat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 04:15:39