'Delay method takes too long on javascript

I'm new to HTML & Javascript and I'm learning the basics of drawing in a canvas. I tried to create a visualization of some search algorithms like BFS and DFS.

So I came up with the following code(shows BFS):

async function bfs_iterative({x,y}) {
    let q = []
    q.push({x,y});
    while(q.length > 0) {
        let v = q.shift();
        let neighbors = get_neighbors(v);
        for(let i = 0; i < neighbors.length; ++i) {
            let neighbor = neighbors[i];
            if(neighbor.x == end_coords.x && neighbor.y == end_coords.y) {
                return;
            }
            main_array[neighbor.y][neighbor.x] = grid_kind['visited'];
            q.push(neighbors[i]);
            await delay();
            update();
        }
    }
}

Update function looks like this:

function update() {
    clear();
    for(let i = 0; i < grid_height; ++i) {
        for(let j = 0; j < grid_width; ++j) {
            switch(main_array[i][j]) {
                case grid_kind['path']: draw_rect(j * unit_width, i * unit_height, unit_width, unit_height, background_color); break;
                case grid_kind['wall']: draw_rect(j * unit_width, i * unit_height, unit_width, unit_height, foreground_color); break;
                case grid_kind['visited']: draw_rect(j * unit_width, i * unit_height, unit_width, unit_height, visited_color); break;
                case grid_kind['solution']: draw_rect(j * unit_width, i * unit_height, unit_width, unit_height, solution_color); break;
            }
        }
    }
    draw_rect(start_coords.x * unit_width, start_coords.y * unit_height, unit_width, unit_height, start_color);
    draw_rect(end_coords.x * unit_width, end_coords.y * unit_height, unit_width, unit_height, end_color);
}

Whenever I try to call update() without the delay, the program waits until the entire search is completed and then updates. I tried finding solutions for this, and I tried using setTimeout() and setInterval() but they didn't work, so I just added a delay.

Delay looks like this:

async function delay() {
    // delay_ms is a global
    return new Promise(resolve => setTimeout(resolve, delay_ms)); 
}

But the problem with this method is that even with a very small delay (0 or 1ms) the program is extremely slow. I was wondering if there was a way to somehow reduce the delay.



Solution 1:[1]

I solved this by only calling the delay and update function once every n iterations. Example:

async function bfs_iterative({x,y}) {
    let q = []
    q.push({x,y});
    let ctr = 0;
    let n = 5;
    while(q.length > 0) {
        // runs every 5 iterations 
        ctr = (ctr + 1) % n;
        if(ctr == 0) { 
            await delay();
            update();
        }
        let v = q.shift();
        let neighbors = get_neighbors(v);
        for(let i = 0; i < neighbors.length; ++i) {
            let neighbor = neighbors[i];
            if(neighbor.x == end_coords.x && neighbor.y == end_coords.y) {
                return;
            }
            main_array[neighbor.y][neighbor.x] = grid_kind['visited'];
            q.push(neighbors[i]);
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ashwin Alagiri-rajan