0

我有一个使用列中组织的项目(div 元素)的网络应用程序,并且在跟踪用户当前选择的项目时遇到问题。

我目前通过保留一个item_id包含所选项目 ID 的内部变量(例如)来做到这一点。删除当前选定的项目将选择已删除项目正下方的项目。当在客户端删除项目时,它会向服务器发送 AJAX 调用。此调用发送要删除的项目的 ID。如果调用成功完成,则item_id更新。我正在使用异步 AJAX 调用。当用户反复(并且非常快!)删除项目时,item_id有时会不同步。我想防止这种行为。

这是我认为这个问题是如何发生的。假设我有一个包含 3 个项目的列表,['apple','banana','coconut']并且'apple'当前已被选中。为了形象化,它看起来像这样。“{}”表示选中的项目,“X”是删除项目的按钮。

+---------+---+
| {apple} | X |
| banana  | X |
| coconut | X |
+---------+---+

然后,可能会发生以下情况。

  1. 用户删除'apple'并启动 AJAX 删除调用'apple'
  2. 用户删除'banana'并启动 AJAX 删除调用'banana'
  3. 第 2 步中的 AJAX 调用首先完成。item_id现在拥有 的 ID 'coconut'
  4. 来自第 1 步的 AJAX 调用终于结束了。'item_id' 现在拥有 的 ID 'banana'

此时,列表中剩下的唯一项目是'coconut',但item_id其 ID'banana'已不存在。这对我来说是个问题。

由于这些调用是异步的,因此它们之间存在竞争。我使用插件来序列化使用队列的 AJAX 调用,但似乎仍然存在调用首先进入队列的竞争条件。

我应该如何实现这一点,以便item_id永远不会不同步并正确指向列表中的选定项目?

编辑:这是我用来删除项目的简化代码。

function deleteItem (item_id) {
    $.ajax({
            type: 'POST',
            url: '/update.php',
            data : {
            item_id : item_id
        }
    })
    .done(function () {
        var deleted_item = $('#' + item_id);
        var nearest_list = deleted_item.next();

        // use the item below if it exists, otherwise get it from above
        nearest_item = nearest_item.length !== 0 ? nearest_item : deleted_item.prev();

        deleted_item.remove();

        if (nearest_item.length === 0) { // i.e. there are no more items in the list
            doSomething();
        } else if (item_id === selected_item_id) { // you deleted a selected item
            var nearest_item_id = nearest_item.attr('id');

            $('#' + nearest_item_id).addClass('selected-item');

            selected_item_id = nearest_item_id;

            loadItem(nearest_item_id);
        }
    })
    .fail(function (err,textStatus,errorThrown) {
        handleError(err,errorThrown);
    }
}
4

1 回答 1

1

你描述的叫溢出。用户单击的速度比您向服务器传达删除的速度快,“多个元素”不适合只能容纳一个元素的容器,因此行为变得未定义(并且不受欢迎)。

解决方案:不要使用单个变量来跟踪删除,使用列表。

  1. 用户点击删除 - >将此元素推送到deletion队列中,禁用页面上的元素,使其无法再被点击(看起来灰显等)。
  2. ajax调用删除到服务器->从deletion队列中弹出元素并将其添加到队列pending
  3. 服务器说“我删除了它”-> 从pending队列中弹出元素并将其从页面中删除。

所以你的想法很好,唯一的问题是你var在实际需要堆栈/队列/数组/列表/whathaveyou时不小心使用了一个。

于 2013-06-08T14:37:08.283 回答