如果之前的搜索返回了很多结果,为什么我的JavaScript搜索速度会慢很多?

Fel*_*bek 5 javascript performance reflow html-rendering

我在写的网络应用程序中有一个非常奇怪的效果.当前搜索结果的数量对下一次搜索的速度有很大影响,即使搜索不会使用结果列表.

我不知道我应该在这里发布多少代码来演示应用程序的功能,但整个应用程序都在http://connective-lex.info上在线.(要查看效果,请选择所有词典,然后更改搜索选项,例如,选中一个或不选.)

这是查询功能.标记的第一行!!!清除先前的结果列表,从而实现快速搜索.如果此行被注释掉,搜索开始的速度会快一些,但如果许多项目位于上一个结果列表中,那么搜索速度会非常慢.

结果列表是this.results,并且未在搜索代码中使用.它也没有在结果实现过滤的ResultsFilter类中使用,为简洁起见,我省略了它,但如果您需要更多代码,我会很乐意发布更多代码.

  // File: c24-components.js
  // Class: ResultsComponent
  ExecuteQuery() {
    setTimeout(() => this.SetResults([]), 0); // !!!
    let tempResults = [];
    let lexIds = Object.keys(gSelectorComponent.lex);
    let totalSize = lexIds.map(lexId => gSelectorComponent.lex[lexId].entry.length).
                                          reduce((acc, val) => acc + val, 0);
    let resultsFilter = new ResultsFilter(totalSize);
    let processAtOnce = 20;

    this.activeSearches.forEach(timeoutId => clearTimeout(timeoutId));
    this.activeSearches.length = 0;

    /* Subfunction which emulates asynchronous processing in the (single-threaded) 
       JS environment by processing a slice of entries and then enqueuing the next 
       slice to be processed so that the browser has time to process user events 
       and render the GUI between slices. */
    let processingFunction = (lexIdIndex, entryIndex) => {
      if (lexIdIndex >= lexIds.length) {
        this.activeSearches.push(setTimeout(() => this.SetResults(tempResults), 0));
        return;
      }

      let entries = undefined;
      try {
        entries = gSelectorComponent.lex[lexIds[lexIdIndex]].entry;
      } catch (e) {
        // This happens when a lexicon is deselected while a search is running.
        // Abort search.
        return;
      }

      for (let i = 0; i < processAtOnce; ++i, ++entryIndex) {
        if (entryIndex >= entries.length) {
          this.activeSearches.push(setTimeout(processingFunction, 0, ++lexIdIndex, 0));
          return;
        }

        if (resultsFilter.TestEntry(entries[entryIndex])) {
          tempResults.push(entries[entryIndex]);
        }
      }

      this.activeSearches.push(setTimeout(processingFunction, 0, lexIdIndex, 
        entryIndex));
    };

    this.activeSearches.push(setTimeout(processingFunction, 0, 0, 0));
  }
Run Code Online (Sandbox Code Playgroud)

更新:如果我正确理解Chrome的效果工具,则这是因更新进度条而导致的重排问题.在每次更新时,JS都会花费大量时间在"更新层树"渲染操作中,这似乎是唯一的区别,如果显示更多的先前结果,则需要更长的时间.我想知道如何摆脱这种效果,但仍然显示进展.