0

我在页面加载时有项目 ID 列表:

var itemIds = [1, 5, 10, 11];

ID 被呈现到列表中并显示给用户。我有加载项目详细信息的函数,它返回 Promise/A。

function loadInfo(id) { ... }

在页面加载时启动所有项目的信息加载:

val infos = {};
$.each(itemIds, function(i, id) { infos[id] = loadInfo(id); }

现在问题本身。

当用户点击项目 ID 时:

  • 如果加载了项目信息,则必须显示信息
  • 如果项目信息尚未加载,则必须在加载时显示

看起来很简单:

$('li').click(function() {
    var id = $(this).data('item-id');
    infos[id].then(function(info) { $('#info').text(info); });
});

但是,如果用户在加载当前项目之前单击了另一个项目,那么我必须取消当前项目承诺的处理程序并安排新项目。

如何正确地做到这一点?

我有几个可行的解决方案(比如维护 currentItemId 变量并在 Promise 处理程序中检查它),但它们很难看。我应该改用反应式编程库吗?

4

1 回答 1

0

克里曼特,

我想您可以通过多种方式对此进行编码。这是一个:

var INFOS = (function(){
    var infoCache = {},
        promises = {},
        fetching = null;

    var load = function(id) {
        if(!promises[id]) {
            promises[id] = $ajax({
                //ajax options here
            }).done(function(info){
                infoCache[id] = info;
                delete promises[id];
            });
        }
        return promises[id];
    }

    var display = function(id, $container) {
        if(fetching) {
            //cancel display (but not loading) of anything latent.
            fetching.reject();
        }
        if(infoCache[id]) {
            //info is already cached, so simply display it.
            $container.text(infoCache[id]);
        }
        else {
            fetching = $.Deferred().done(function() {
                $container.text(infoCache[id]);
            });
            load(id).done(fetching.resolve);
        }
    }
    return {
        load: load,
        display: display
    };
})();

正如您将看到的,所有复杂性都捆绑在 namespaceINFOS中,它公开了两种方法;loaddisplay

以下是调用方法的方法:

$(function() {
    itemIds = ["p7", "p8", "p9"];

    //preload
    $.each(itemIds, function(i, id) { INFOS.load(id); });

    //load into cache on first click, then display from cache.
    $('li').on('click', function() {
        var id = $(this).data('item-id');
        INFOS.display(id, $('#info'));
    });
});

DEMO(带模拟 ajax)

这里的技巧是:

  • 缓存由 id 索引的信息
  • 缓存活动的 jqXHR 承诺,由 id 索引
  • 如果以前加载过,则显示缓存中的信息...
  • ...否则,每次请求信息时,创建一个与信息显示关联的延迟,可以独立于相应的 jqXHR 解决/拒绝。
于 2013-01-23T02:57:34.597 回答