如何正确选择仍然使用承诺加载的项目?

时间:2013-01-22 03:31:31

标签: javascript promise

我在页面加载时有项目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处理程序中检查它),但它们很难看。我应该寻找反应式编程库吗?

1 个答案:

答案 0 :(得分:0)

Kriomant,

我想有很多方法可以对此进行编码。这是一个:

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
    };
})();

正如您将看到的,所有复杂性都捆绑在命名空间INFOS中,这会暴露两种方法; 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解析/拒绝。