首页 > 解决方案 > 为什么我的阵列只在视图中更新一次?

问题描述

我正在做一个项目来帮助可视化排序算法,但我遇到了一个问题。
为了帮助可视化算法的排序过程,我必须在所述过程中显示数组中的每一个变化。
问题是我的数组仅在排序完成后才在我的视图中更新,而不是在此过程中。
我的数组中只有整数。

这是我显示数组的代码:

<span *ngFor="let v of tab">
    {{v}}
</span

这是我的控制器:(超时用于减慢进程)

public sort(tab) {
let start = performance.now();
console.log(start);
let smallest;
for (let i = 0; i < tab.length; i++) {
  smallest = tab[i];
  for (let j = i + 1; j < tab.length; j++) {
    setTimeout(() => { }, 100000);
    if (tab[j] < smallest) {
      let tmp = tab[j];
      tab[j] = smallest;
      tab[i] = tmp;
      smallest = tmp;

      //This doesn't update the view
      this.tab = tab;
    }

  }
}
//This does
this.tab = tab;
let end = performance.now();
console.log(end);
this.time = end - start;

该算法可能不是最有效的,但事实并非如此^^。

标签: htmlarraysangulartypescriptsorting

解决方案


这是因为

setTimeout(() => { }, 100000);

不是同步操作。它不会为下一个操作等待 100000 毫秒,它只会继续同步操作并安排其他时间超时(您可以阅读 JavaScript 中的事件循环以了解该部分)

有几种方法可以解决这个问题,你可以做递归(不是很好),你可以创建一个异步函数(你可以阅读 javascript 中的 async/await),你可以使用 RxJS 的响应式方法(Angular 已经在使用它),所以像:

const sort = (tab: number []) => {

  let smallest: number;

  // First "loop" (iterate i (0, 1, 2, 3 ...))
  range(0, tab.length)
    .pipe(
      // Set smallest
      tap(i => smallest = tab[i]),
      // Second loop (i + 1, i + 2, i + 3 ...) and map i and j to [i, j] 
      mergeMap((i: number) => range(i + 1, tab.length - i - 1).pipe(map(j => [i, j]))),
      // Make delay
      concatMap(x => of(x).pipe(delay(1000)))
    ).subscribe(([i ,j]) => {

    if (tab[j] < smallest) {

      [tab[i], tab[j]] = [tab[j], tab[i]];
      smallest = tab[j];

      // Here if you can set
      // this.tab = tab; and you will see changes
    }

  })

}

推荐阅读