fs read strange behavior

Hello,

I was writting a service to load/save the user configuration in a file and I noticed a strange behavior.

The config file was read properly when “force reloading” the application (Ctrl+Shift+R) but, each time I launch the app for the first time (npm start), the configuration was empty.

I noticed that the callback of fs.read() was never hit just after ‘npm start’…

Here is a sample project to reproduce the problem: angular-electron – fs read problem

I modified ElectronService to expose path so I could use path.sep, created a basic ConfigService that reproduce the issue and did a test in the AppComponent that loads the config and, after 5 seconds, verifies the content of the config and writes a new one if it’s empty.

The config service:

import { Injectable } from '@angular/core';
import { ElectronService } from '../electron/electron.service';

@Injectable({
  providedIn: 'root'
})
export class ConfigService {

  private config: any;
  protected fileName: string = 'application-config.json';
  protected _filePath: string;
  protected get filePath(): string {
    if (this._filePath) return this._filePath;
    const userDataPath = this.electron.remote.app.getPath('userData');
    this._filePath = `${userDataPath}${this.electron.path.sep}${this.fileName}`;
    return this._filePath;
  }

  constructor(
    private electron: ElectronService
  ) { }

  load() {
    console.log('loading config...');
    this.electron.fs.readFile(this.filePath, { encoding: 'utf8'}, (err, data) => {
      console.log('config loaded...');
      if (err) return console.error(err);
      if (!data) return console.warn(`application configuration file '${this.filePath}' exists but is empty`);
      try {
        this.set(JSON.parse(data));
      }
      catch (ex) {
        console.error(`an exception occured while parsing configuration file '${this.filePath}'`, ex);
      }
    });
  }

  set(config: any) {
    this.config = config;
    this.save();
  }

  get() {
    return this.config;
  }

  private save() {
    console.log('saving config...');
    this.electron.fs.writeFile(this.filePath, JSON.stringify(this.config), { encoding: 'utf8', flag: 'w+' }, (err) => {
      console.log('config saved.');
      if (err) return console.error(err);
    });
  }
}

The test procedure in AppComponent:

    configSvc.load();
    setTimeout(() => {
      const config = configSvc.get();
      if (!config) {
        console.log('no config, setting default');
        configSvc.set({ foo: 'bar'});
      }
      else {
        console.log('got config', config);
      }
    }, 5000);

When launching the app for the first time, a config file with ‘{“foo”:”bar”}’ should be created. If you reload the app using the developer tools, you should see the config loads properly. But, if you close the app and relaunch it using npm start, you’ll notice the log “config loading…” in the console but “loaded config…” will never be displayed and a new mock config will be written.

An even stranger thing is that the Sync version of read doesn’t seem to be affected by this behavior. Replacing the config service by the following seem to work as expected:

import { Injectable } from '@angular/core';
import { ElectronService } from '../electron/electron.service';

@Injectable({
  providedIn: 'root'
})
export class ConfigService {

  private config: any;
  protected fileName: string = 'application-config.json';
  protected _filePath: string;
  protected get filePath(): string {
    if (this._filePath) return this._filePath;
    const userDataPath = this.electron.remote.app.getPath('userData');
    this._filePath = `${userDataPath}${this.electron.path.sep}${this.fileName}`;
    return this._filePath;
  }

  constructor(
    private electron: ElectronService
  ) { } 

  load() {
    console.log('loading config...');
    try {
      const configStr = this.electron.fs.readFileSync(this.filePath, { encoding: 'utf8'});
      console.log('config loaded...');
      if (configStr) this.set(JSON.parse(configStr));
    }
    catch (ex) {
      console.error(ex);
    }
  }

  set(config: any) {
    this.config = config;
    this.save();
  }

  get() {
    return this.config;
  }

  private save() {
    console.log('saving config...');
    this.electron.fs.writeFileSync(this.filePath, JSON.stringify(this.config), { encoding: 'utf8', flag: 'w+' });
    console.log('config saved.');
  }
}

I can’t really figure where the issue comes from. Did I miss something or is it a but of some kind?

Thanks for your help, best regards.

1 possible answer(s) on “fs read strange behavior

  1. This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.