DOM redraw being blocked by childProcess.spawnSync


#1

I have an electron/node.js app that I’m having trouble with. Specifically, I need to give the user some feedback on the progress of a long loop of synchronous spawns by updating an element in the DOM. However, what is actually displayed does not change during the loop. Once the entire loop is complete, the element does update with the final max index value.

function dosomething(index,callback) {
   childProcess.spawnSync('app1',...  //takes 1 second
   childProcess.spawnSync('app2',...  //takes 6 seconds, depends on app1 running 1st
   console.log('working on: ' + index);
   callback(index);
}

function dosomethingelse(index) {
    $('#somediv').html(index);  //update progress bar
    console.log('displaying: ' + $('#somediv').html());
}

for(var i=0; i<max; i++){ //max is usually 10-100, loop takes 1 to 10 minutes
    dosomething(i,dosomethingelse);
}

When I dump the progress html to the console, it does increment with index as a callback:

CONSOLE:
working on: 0
displaying: 0
working on: 1
displaying: 1
working on: 2
displaying: 2
...

Also, I have tried to force redraw the div by adding the following code to no avail:

function dosomethingelse(index) {
    $('#somediv').html(index);  //update progress bar
    console.log($('#somediv').html());
    //REDRAW
    document.getElementById("somediv").innerHTML =num;
    document.getElementById("somediv").style.display = 'none';
    document.getElementById("somediv").offsetHeight;
    document.getElementById("somediv").style.display = 'block';
}

#2

It’s quite possible that the jQuery operation you’re calling is asynchronous and is yielding expecting other long-running operations to yield too. But since you’re using synchronous code, they aren’t yielding and so the asynchronous code gets pushed all the way to the end.

Have you tried using some other long-running synchronous operation other than childProcess.spawnSync? I suspect there is nothing special about spawnSync that is causing the problem.


#3

That makes sense. Node is blasting through all the async code and getting to my blocking code in the loop and getting hung up completing those tasks. I’ve tried using deasync:

var deasync = require('deasync');
deasync(dosomething(i));
dosomethingelse(i);

When I use the blocking npm sleep function for 3 seconds instead of my spawnSync I do get the same result. Any way to ‘pause’ the blocking loop to allow the UI to update?


#4

You could use spawn instead of spawnSync. The spawn version is asynchronous.