Typeahead、Bloodhound:远程工作,但预取不起作用

14

我想使用预取(prefetch),但它无法正常工作!这是我的代码:

function initAutocompletion() {
    $("input[data-autocomplete-prefetch-url]").each(function () {
        var $this = $(this);
    var urlPrefetch = $this.data("autocomplete-prefetch-url");
    var prefetch;

    pref = {
        url: urlPrefetch,
        filter: filter
    };

    var bloodHound = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 10,
        prefetch: pref
    });

    bloodHound.initialize();

    $this
        .typeahead('destroy')
        .typeahead({
            hint: true,
            highlight: true,
            minLength: 1
        },
        {
            displayKey: 'value',
            source: bloodHound.ttAdapter()
        });
    });
 }

function filter(list) {
    return $.map(list, function (v) { return { value: v.toString() }; });
}

它不能运行。

如果我使用远程而不是预取,它就能工作!

    var bloodHound = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 10,
        remote: pref
    });

我不理解。

有人可以帮帮我吗?

4个回答

20

今天早上神奇地解决了! 所以我想这应该是缓存的问题...果然如此! 在初始化Bloodhound之前添加clearPrefetchCache()就搞定了。

       bloodHound.clearPrefetchCache();
       bloodHound.initialize();
我认为它没有显示任何建议,因为它已经缓存了一个空列表。

官方提供的预取示例在没有使用clearPrefetchCache的情况下无法正常工作。在initialize之前添加clearPrefetchCache有所帮助,但并没有解释具体原因。 - Gherman
1
值得注意的是,根据您的应用程序,这可能不是一个很好的生产方案,因为如果您在每次页面加载时清除预取缓存,则必须在每次页面加载时重新加载数据到缓存中,因此您只能在切换页面或重新加载当前页面之前获得缓存的优势。但对于开发环境来说,这可能是一个绝佳的想法。 - Tony

10

这是因为 typeahead 已经从预获取的 URL 中加载了您的数据并将其存储在 localStorage 中。当数据在 localStorage 中时,不会调用预获取。

尝试更改 prefetch 选项中的 cacheKey,并重新加载页面。由于在 localStorage 中没有与新 cacheKey 相关联的数据,预获取将被调用。

var engine = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  prefetch: {
    url: "stations.json",
    cacheKey: "change here!"
  }
});

您也可以使用Chrome开发者工具检查本地存储。

enter image description here

尝试删除本地存储数据并重新加载页面。预取将被激活。

在Bloodhound初始化之前删除localStorage数据,以便在每次初始化时都会触发其预取。

localStorage.removeItem("YOUR CACHEKEY");

// Bloodhound initialization with YOUR CACHEKEY.

clearPrefetchCache()initialize()之前使用更好,我认为。


.initialize(true) 每次调用时都会清除缓存。 - Zachary Dahan
很棒的信息,但并没有提供解决方案。 - Megan Caithlyn
@Stuffix 我不这么认为。在我的测试环境中,我使用了.initialize(true)。如果我在初始化之前删除.clearPrefetchCache(),那么预取将停止命中我的服务器。根据我的实验(版本0.11.1),如果您想要清除预取缓存,您必须在.initialize(true)之前调用.clearPrefetchCache() - davew
@davew 你可能是对的,我写下这条评论已经有3年了,所以事情可能已经发生了变化。我自那以后就没有再碰过typeahead。 - Zachary Dahan

2

我在解决remote正常工作但prefetch无法工作的问题时,发现了您的问题。我首先解决了缓存问题(因为之前出现过这个问题),但它仍然不能正常工作。

接下来,我在typeahead中实现了templates,以便在单击和键入字段时获取一些反馈,但是没有任何响应。 我会看到notFound模板出现。 这似乎很奇怪,因为我可以看到prefetch命中了服务器。 通过在服务器上使用调试输出,我还可以知道服务器正在生成正确的json响应。

但是,在检查json时,我注意到它没有空格,并且我的bloodhound的datumTokenizer配置为Bloodhound.tokenizers.whitespace。 这促使我更深入地研究词汇标记器的工作原理。

我发现这非常有帮助:https://github.com/twitter/typeahead.js/blob/master/doc/migration/0.10.0.md#tokenization-methods-must-be-provided

在切换到以下内容后,我的问题得到了解决:

datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.value);

(其中.value是我想要搜索的JSON属性)

请问您能详细解释一下令牌生成器吗?我们不明白为什么在预取和远程情况下它们会有所不同。链接 - for_all_intensive_purposes

0

可能是您尝试在urlPrefetch获取值之前预取数据。请尝试将urlPrefetch转储到控制台并检查它是否具有有效的URL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接