跟踪HTML中所选div元素的ID?

时间:2013-06-08 06:33:08

标签: javascript ajax race-condition

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

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

以下是我认为这个问题是如何发生的。假设我列出了3个项目['apple','banana','coconut'],目前已选择'apple'。为了可视化,它看起来像这样。 “{}”表示所选项目,“X”是用于删除项目的按钮。

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

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

  1. 用户删除'apple',并启动了删除'apple'的AJAX调用。
  2. 用户删除'banana',并启动了删除'banana'的AJAX调用。
  3. 第2步的AJAX调用首先完成。 item_id现在拥有'coconut'
  4. 的ID
  5. 第1步的AJAX调用终于完成了。 'item_id'现在包含'banana'
  6. 的ID

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

    由于这些调用是异步的,因此它们之间存在竞争。我使用插件来序列化使用队列的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);
        }
    }
    

1 个答案:

答案 0 :(得分:1)

您描述的内容称为溢出。用户点击的速度比将删除信息传递给服务器的速度快,“多个元素”不适合只能容纳一个元素的容器,因此行为变得不明确(并且不合需要)。

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

  1. 用户点击删除 - >将此元素推送到deletion队列,禁用页面上的元素,使其不再被点击(看起来变灰等)。
  2. ajax调用删除服务器 - >来自deletion队列的pop元素,并将其添加到pending qeueu
  3. 服务器说“我删除了它” - >弹出pending队列中的元素并将其从页面中删除。
  4. 所以你的想法很好,唯一的问题是当你真正需要一个堆栈/队列/数组/列表/ whathaveyou时,你不小心使用了一个var