【问题标题】:how to stop array.filter() function如何停止 array.filter() 函数
【发布时间】:2018-05-25 03:26:19
【问题描述】:

我正在使用自定义搜索过滤器

HTML

 <input type="text" pInputText class="ui-widget ui-text" [(ngModel)]
 ="gloablFilterValue" (ngModelChange)="splitCustomFilter()" placeholder="Find" />

我在搜索框上使用ngModelChange() 事件


globalSearch(realData, searchText, columns) {
        searchText = searchText.toLowerCase();
        return realData.filter(function (o) {
            return columns.some(function (k) {
                return o[k].toString().toLowerCase().indexOf(searchText) !== -1;
            });
        });
    }

    splitCustomFilter() {
    let columns =  
   ['PartNoCompleteWheel', 'DescriptionCompleteWheel', 'PartNoTyre', 'DescriptionTyre', 'PartNoRim', 'DescriptionRim','DeletedDateFromKDPStr', 'DateFromKDPStr', 'Status'];
   this.tyreAndRimList = this.globalSearch(this.tyreAndRimList, this.gloablFilterValue, columns); 
    }

this.tyreAndRimList 变量中提到的列的值列表 column

问题

过滤器运行良好!但主要问题是过滤器性能很差,而记录数很大(每列超过 100 行)

何时

如果输入单个字符(如a),过滤器会正常工作。但是当我连续输入字符时,浏览器就挂了。原因是过滤器一直在触发过滤器框上的每次输入(因为我正在使用ngModelChange()// onchange() 事件)

我想要什么

如果用户在搜索框中连续输入,我想停止过滤。一旦用户停止输入,那么我只需要开始过滤。

我做了什么

我尝试使用setTimeout() 来处理这个问题。但它只是等待过滤器调用一秒钟。如果用户只连续输入 2 或 3 个字符,它就可以工作。但如果用户输入超过 7 个或 8 个或以上的字符,它会继续挂起浏览器。因为许多过滤器回调同时处理。

 setTimeout(() => //code of filtering ,1000);

问题

如何在用户连续输入值时停止过滤,在用户停止输入后开始过滤?

我正在使用 angular-2 和 typescript。但是这个问题与angularjsangularJavaScripttypescript 无关,因为我想要一个想法而不是解决方案。所以我会为这个问题添加所有标签。不要删除它。谢谢

【问题讨论】:

  • 您无法在完成之前停止filter。另一方面,您可以使用for 循环,您可以使用break。其他可能性:debounce your filter
  • 你需要debounce活动。
  • 所以看看去抖动,如果过滤了,当他们再输入一个字符时就不需要过滤整个列表,只需过滤过滤后的集合。
  • 当然是去抖动,但除此之外,您还可以进一步优化代码。例如,您可以(假设文本是静态的)在每行所有单元格的初始化期间创建一个连接字符串。然后只检查每行连接的字符串。这样您就可以跳过过滤器中的所有列+strtolower 的循环。

标签: javascript arrays angular typescript


【解决方案1】:

去抖函数。看看下划线是怎么做的:Function Debouncing with Underscore.js

然后你会像这样生成你的函数的去抖动版本:

var globalSearchDebounced = _.debounce(globalSearch, 100, false);

它只会在用户停止输入至少一秒钟后调用。

【讨论】:

  • 此解决方案的替代方案是使表单具有反应性,订阅输入的值更改,然后应用 rxjs debounce 运算符。还可以在执行数组过滤器之前添加其他运算符,例如过滤器以强制最少数量的字符。
  • 您不能“只复制 14 行”。当您使用部分代码时,仍有一个许可条款必须遵守。
  • @IngoBürk 是真的。违规的句子被删除。
【解决方案2】:

无法中断Array.filter 方法。根据您的需要,您可以这样处理:

let timerId = null

function handleChange() {
  if(timerId) {
    clearTimeout(timerId)
  }

  timerId = setTimeout(() => /* Array.filter(...) */, 1000)
}

说明

有一个变量将包含从setTimeout 函数返回的timerId。每次更改模型时,都会调用 handleChange 函数(在此示例中)。该函数检查是否设置了包含timerId 的变量并包含timerId,当变量包含timerId 时,将调用clearTimeout 函数以清除先前的超时,之后handleChange 创建一个新的超时并将timerId(从setTimeout 函数返回)分配给变量。

【讨论】:

    【解决方案3】:

    没有下划线,也没有 Timeout(顺便说一句,这将触发整个 Angular 生命周期),您可以使用带有异步管道和去抖动的 Observable。

    在您的全局搜索功能中:

    return Observable.of(/* filter here and return the filtered array */).debounceTime(1000)
    

    在你的列表中(我猜肯定在某个地方)

    <list-item *ngFor="let x of myFilteredResults | async">...</list-item>
    

    【讨论】:

    • 错误; `Observable`的类型不存在属性of
    • import 'rxjs/add/observable/of';
    • import 'rxjs/Rx';(这是一种不好的做法,但它可以让您测试它是否按您的意愿工作)
    【解决方案4】:

    我已经使用SubjectdebounceTime 完成了它。

    private subject = new Subject<string>()
    ngOnInit() {
            this.subject.debounceTime(300).subscribe(inputText => {
            this.gloablFilterValue = inputText;
            this.splitCustomFilter();   // filter method  
            });    
        }
    

    现在,当我使用 change 事件更改 this.gloablFilterValue 对象中的值时。它只是等待事件完成的结束。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2014-06-18
      • 2012-04-04
      • 2022-01-21
      相关资源
      最近更新 更多