【问题标题】:Replaced timeout event fires twice or more (sometimes)替换的超时事件触发两次或更多次(有时)
【发布时间】:2023-04-10 05:00:01
【问题描述】:

我有一段内容允许用户在双击它时对其进行编辑。如果用户更改内容后停顿2秒,则将更新后的内容发送到服务器进行保存。

为此,我已将input 事件侦听器绑定到开始 2 秒倒计时的那个部分,如果已经有倒计时,则前者将被取消并开始一个新的倒计时。在倒计时结束时,会向服务器发送一个带有新数据的 http POST 请求。

问题是,有时在倒计时结束时,我会看到发送了 2 个或更多请求,就好像在插入新请求之前没有取消倒计时一样,我不知道为什么。

有问题的代码如下:

//this function is bound to a double-click event on an element
function makeEditable(elem, attr) {

    //holder for the timeout promise
    var toSaveTimeout = undefined;

    elem.attr("contentEditable", "true");
    elem.on("input", function () {

        //if a countdown is already in place, cancel it
        if(toSaveTimeout) {
            //I am worried that sometimes this line is skipped from some reason
            $timeout.cancel(toSaveTimeout);
        }
        toSaveTimeout = $timeout(function () {
            //The following console line will sometimes appear twice in a row, only miliseconds apart
            console.log("Sending a save. Time: " + Date.now());
            $http({
                url: "/",
                method: "POST",
                data: {
                    action: "edit_content",
                    section: attr.afeContentBox,
                    content: elem.html()
                }
            }).then(function (res) {
                $rootScope.data = "Saved";
            }, function (res) {
                $rootScope.data = "Error while saving";
            });
        }, 2000);
    });

    //The following functions will stop the above behaviour if the user clicks anywhere else on the page
    angular.element(document).on("click", function () {
        unmakeEditable(elem);
        angular.element(document).off("click");
        elem.off("click");
    });
    elem.on("click", function (e) {
        e.stopPropagation();
    });
}

【问题讨论】:

  • 您是否尝试将console.log 添加到if(toSaveTimeout) { 块中以查看它是否进入其中?
  • 每次调用 makeEditable 函数时,您的 toSaveTimeout 都是未定义的,因为它绑定到此函数范围。您的测试if(toSaveTimeout) 将始终失败。
  • 确保您不要两次调用makeEditable
  • @Franck:我认为用户只会双击那些。所以用户双击,然后开始输入输入。每次输入输入后,它应该等待 2 秒并向服务器发送请求。如果用户在 2 秒之前再次输入,它应该取消 2 秒计时器。对我来说就是这样。
  • 好的,是的 :-(。这就是问题所在。当元素已经处于可编辑状态时,双击并再次双击似乎是问题的唯一原因。谢谢

标签: javascript angularjs settimeout


【解决方案1】:

事实证明(在上述评论员的帮助下)函数 makeEditable 被多次调用。

在函数开头添加以下两行代码解决了这个问题:

//if element is already editable - ignore
if(elem.attr("contentEditable") === "true")
    return;

【讨论】:

  • 你知道为什么/如何makeEditable 被调用了两次吗?无论如何要停止/修复它,所以它永远不会被调用两次,而不是检查它是否已经被调用?我的意思是,两者都有效,但我觉得从源头停止它会更好。
  • (您可能还想将您的答案标记为答案。)
  • 发生这种情况的原因有很多,甚至可能是硬件问题,例如疯狂的鼠标发送多次鼠标点击。但其中一个原因也是用户再次双击只是原因(也许他/她不理解这个概念或认为这是保存的方法),并且在这种情况下防止问题浮出水面的唯一方法是上面的代码行。 (是的,我会的,但规则会在接受您自己的答案前 24 小时声明)
猜你喜欢
  • 1970-01-01
  • 2011-01-08
  • 2014-04-07
  • 1970-01-01
  • 2017-01-02
  • 2017-12-19
  • 1970-01-01
相关资源
最近更新 更多