使用localStorage进行乐观更新。这是不好的设计吗?

时间:2016-01-02 21:42:52

标签: javascript ajax asynchronous concurrency

情境:

所以我有一个javascript组件基本上包含一些全局数据列表的实例(在我的实际应用程序中,它存在于Flux Store中,但为了简单起见,我只是将其称为全局变量)。 / p>

它包含通过对REST API进行AJAX调用来添加/删除数据的函数。


设计

由于我希望用户能够立即查看更新的列表,而不是等到Ajax成功回调,我正在执行“乐观更新”。

也就是说,我在执行实际的AJAX调用之前更新列表,同时在localStorage中保留列表的原始副本以防AJAX调用失败。

(1)如果AJAX调用成功,则使用API​​响应更新列表(基本上应与乐观更新的列表相同)

(2)如果AJAX调用失败,则通过从localStorage检索原始副本来撤消乐观更新。


这是我的实施

// Some global data list
var myData = ["data1", "data2", ...];

function addData(dataToAdd) {
    // Store original in cache before optimistic update
    localStorage.set("MY_DATA", myData);
    // Do optimistic update
    myData = myData.concat(dataToAdd);

    $.ajax({
        url: REST_API_ADD,
        method: "POST",
        data: { data: dataToAdd },
        dataType: "json",
        success: function(response) { 
            // API returns the updated list when success
            myData = response;
        },
        error: function(xhr, status, err) { 
            console.log(err);
            // Cancel optimistic update and retrieve old data from cache
            myData = localStorage.get("MY_DATA");
        }
    }); 
}

function deleteData(dataToDelete) {
    // Store original in cache before optimistic update
    localStorage.set("MY_DATA", myData);
    // Do optimistic update
    // I'm using Underscore.js here to delete data from list
    myData = _.without(
        myData,
        _.findWhere(myData, {id: dataToDelete.id})
    );

    $.ajax({
        url: REST_API_DELETE,
        method: "DELETE",
        data: { data: dataToDelete },
        dataType: "json",
        success: function(response) { 
            // API returns the updated list when success
            myData = response;
        },
        error: function(xhr, status, err) { 
            console.log(err);
            // Cancel optimistic update and retrieve old data from cache
            myData = localStorage.get("MY_DATA");
        }
    }); 
}

这个想法有什么问题吗?

我主要担心的是当用户几乎同时执行ADD和DELETE操作时可能出现的竞争条件。

我已经考虑过可能的场景,但似乎并发性在我的情况下不是问题,因为回调函数永远不会修改localStorage。他们所做的只是“得到”。

有人能想到我的设计可能会导致问题的情况吗?

整体上这是一个糟糕的设计吗?如果是这样,那么你可以建议一种替代方法吗?

由于

2 个答案:

答案 0 :(得分:0)

  

我主要担心的是用户可能出现的竞争状况   几乎同时执行ADD和DELETE操作..

这里不应该担心,因为在并行方面,从UI线程执行的AJAX不是异步。 Web浏览器使用执行队列,其中每个排队的操作同步出列。

例如,您永远不会同时修改DOM并执行AJAX请求。实际上,UI任务比AJAX更优先,但无论如何它们将被逐一执行。

AFAIK,你只有一次机会遇到并发问题:Web workers。除非你使用它们,否则你绝对安全。

答案 1 :(得分:0)

我认为这不是一个糟糕的设计,但您仍然可以更好地控制用户。至少你可以阻止他们在ajax呼叫等待成功时采取另一个动作。

我可以想到一个问题:如果你正在处理大量数据,写入和读取localStorage可能会导致性能问题。

除此之外,你的方法应该没有任何问题。