I'm currently working on an Electron.js app and I'm stuck on an asynchrony problem. I have three function (downdloadFile()) inside three if statements to be executed in sequence but they run asynchronously; I already tried using async/await but it didn't worked. Here's my code:
ipcMain.on('play',(event,payload) => {
launcherConfig.savedRam = payload.savedRam;
launcherConfig.savedMaxPermSize = payload.savedMaxPermSize;
if(payload.selectedPacket) {
//FIRST IF
if (!fs.existsSync(launcherDir + "\\natives")) {
downloadFile("http://soulnetwork.it/launcher/natives.zip", launcherDir + "\\natives.zip", true, 'natives');
}
//SECOND IF
if (!fs.existsSync(launcherDir + "\\bin")) {
downloadFile("http://soulnetwork.it/launcher/bin.zip", launcherDir + "\\bin.zip", true, 'bin');
}
//THIRD IF
if (launcherConfig.installed_modpacks.includes(payload.selectedPacket)) {
launchMinecraft(payload.selectedPacket);
saveConfig();
} else {
downloadFile(`http://soulnetwork.it/launcher/modpacks/${payload.selectedPacket}.zip`, launcherDir + "\\modpacks\\" + payload.selectedPacket + '.zip', true, payload.selectedPacket, launchMinecraft);
launcherConfig.installed_modpacks.push(payload.selectedPacket);
saveConfig();
}
}
}
function downloadFile(file_url , targetPath, showProcess, packetName, callback){
// Save variable to know progress
var received_bytes = 0;
var total_bytes = 0;
var req = request({
method: 'GET',
uri: file_url
});
var progressWindow = null;
if(showProcess){
progressWindow = new BrowserWindow({width: 300, height: 60, title: `Downloading ${packetName}`,icon: '../public/images/sn.png'})
progressWindow.setProgressBar(0.0);
progressWindow.loadURL('file://' + __dirname + '/views/download.ejs');
progressWindow.setMenu(null);
}
var out = fs.createWriteStream(targetPath);
req.pipe(out);
req.on('response', function ( data ) {
// Change the total bytes value to get progress later.
total_bytes = parseInt(data.headers['content-length' ]);
});
req.on('data', function(chunk) {
// Update the received bytes
received_bytes += chunk.length;
if(showProcess)
showProgress(progressWindow,received_bytes, total_bytes);
});
req.on('end', function() {
if(showProcess)
progressWindow.close();
if(targetPath.includes('.zip')){
var zip = new archiver(targetPath);
zip.extractAllTo(targetPath.substr(0,targetPath.length-4-packetName.length));
fs.unlinkSync(targetPath);
}
if(callback)
callback(packetName);
console.log("RETURN");
return;
});
}
Using the callback system creates so much caos and it is also redundant, I was hoping for another solution. Thank you for your time!
I can see you are affecting launcherDir in all three times using it in the !if will always execute the first process even if it fails i.e the last if will be checking launcherDir + "\natives" + "\bin" or is this the desired behaviour if not i think all your if's will fail
Where you currently
console.log("RETURN")
you can resolve a Promise which is returned bydownloadFile
. Then you can simply await the calls in yourif
branches (and passasync
callback toipcMain
of course).The structure in a more simple form would look like the followings