-1

i am doing a project to help visualize sorting algorithms and I'm facing a problem.
To help visualize the sorting process of an algorithm, I must show every changings in the array during that said process.
The problem is that my array is updating in my view only once the sort is done and not during the process.
There are only integers in my arrays.

Here is my code to display the array :

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

And here is my controller : (the timeout is used to slow down the process)

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;

The algo is probably not the most efficient but that's not the case ^^.

Bolo
  • 1
  • 2
  • https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep – Cyclonecode Oct 16 '21 at 22:51
  • @Cyclonecode whats the point ? i don't have a problem with my timeOut – Bolo Oct 16 '21 at 22:55
  • Of course you do? It is not like it the above call to `setTimeout()` will wait before continuing with the next iteration? – Cyclonecode Oct 16 '21 at 23:13
  • 1
    @Cyclonecode changed the way i timed out with your answer and it worked thank you ! I did not understand but now i do thanks again – Bolo Oct 16 '21 at 23:38

1 Answers1

1

Its because

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

is not a synchronous operation. It will not wait for 100000ms for the next operation, it will just continue with synchronous operations and schedule timeout for some other time (You can read about Event Loop in javascript to understand that part)

There are several ways to resolve this, you can do recursion (not really good), you can make an async function (you can read about async/await in javascript), and you can use reactive approach with RxJS (Angular is using it already), so something like:

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
    }

  })

}
munleashed
  • 1,677
  • 1
  • 3
  • 9
  • thank you for your answer it helps me a lot to understand the problem I used await/async and it works perfectly thank you – Bolo Oct 16 '21 at 23:51
  • You can take a look at my example as well. I put it just for you to realise the power of RxJs and how it can be done in a "functional" way... Probably you would use it for this example but its good to understand power of Rxjs – munleashed Oct 16 '21 at 23:52
  • i definitely will dont worry ! thanks ! – Bolo Oct 16 '21 at 23:53
  • @Bolo if you think this answer was helpful and solved you issue consider marking it as correct and perhaps add an upvote as well. – Cyclonecode Oct 17 '21 at 09:52