Best Method to access the latest plugin setting values

I want to access the latest values of the setting values of my plugin. That is, the setting values after a user make changes in the settings tab. For this I found the following 3 method.

Method 1 : Using Plugin Class

main.ts :

export default class ThePlugin extends Plugin {

	onload() {
		await this.loadSettings();
		// Rest of my code...
	}
	
	async loadSettings() {
        this.settings = Object.assign({}, await this.loadData());
    }
    
    async saveSettings() {
        await this.saveData(this.settings);
    }
}

Any file, which is not linked from main.ts :

import type <youPluginName> from '../main';
  
export function <name> (
    plugin: <youPluginName>,
): Promise<void> {
    console.log(plugin.settings.<anyOptionYouWantToAccess>);
}

Problem : The issue with this method I am facing is, whenever user makes any changes in the setting from the settings Tab, the data gets reflected in the data.json file. But after this update in the setting if the plugin tries to access the values of the setting, the old data which was loaded at the time of Obsidian startup is given back using the plugin.settings. So, after any changes in the settings, the user will have to restart Obsidian every time for the setting changes to take effect.

Method 2 : By reading the data.json file every time

I can create a function, which i can able to call from any file throughout my project and get the latest values of the setting values of my plugin.

Problem : I make use of the plugin setting values at a lot of places in my code and for many functionalities. This will be too many Disk read/write operations. So this will be the most horrible method. Because the only thing i want to avoid is Disk read/write operations.

Method 3 : By using localStorage

I can load the data from the data.json when the plugin loads and store it in the localStorage. Then i can simply create a function, which will return me any value of my plugin settings. Also, when the user will make any changes in the setting, i will store that in the localStorage as well as in the data.json. But while reading, now i dont have to read the data.json, i can simply read from localStorage.

Problem : I have a question here. I don’t know much about how localStorage works and specially in electron. Some sources say it’s stored on Disk using a database provided by electron. If, it’s a Database, then also this will be too many Disk read/write operation. Although this will be a much better approach then Method 2.

Obviously, ill improve my codebase to pass values parent entity to child entity, as much as possible. But still, i am doing few operation related to events, like detecting file modification in Obsidian. So, when the user will going to make contineous changes in a file, it will be detected as modified and then i am doing few checks, for which i need plugin’s setting values.

Question 1

Am i doing anything wrong in the above method, or obsidian only provides the values which are loaded at the obsidian startup?

Question 2

2.1 : When we do the setItem in the localStorage, where does it actually gets stored is it in RAM or its on Disk inside a Database?
2.2 : I also came across sessionStorage, will it be recommended to use ?

Better Example for Method 1

main.ts :

export default class ThePlugin extends Plugin {

	onload() {
		await this.loadSettings();
		// Rest of my code...

        this.registerEvent(
			this.app.vault.on("modify", (file: TFile) =>
				onFileModified(
					file,
					this.settings.scanFilters
				)
			)
		);
	}
	
	async loadSettings() {
        this.settings = Object.assign({}, await this.loadData());
    }
    
    async saveSettings() {
        await this.saveData(this.settings);
    }
}

Any file.ts :

  
export function onFileModified ( file: TFile, scanFilters: string ): Promise<void> {
    console.log(scanFilters); // I get old value even after user change this in Setting Tab
}

What is the code for your settings tab?

I am rendering the following SettingsManager inside my PluginSettingTab class which extends PluginSettingTab :

export class SettingsManager {
	win: Window;
	app: App;
	plugin: SamplePlugin;
	globalSettings: globalSettingsData | null = null;

	constructor(app: App, plugin: TaskBoard) {
		this.app = app;
		this.plugin = plugin;
	}

	// Function to load the settings from data.json
	async loadSettings(): Promise<void> {
		try {
			const settingData = this.plugin.settings.data.globalSettings;
			this.globalSettings = settingData;
		} catch (err) {
			console.error("Error loading settings:", err);
		}
	}

	// Function to save settings back to data.json
	async saveSettings(): Promise<void> {
		if (!this.globalSettings) return;

		try {
			this.plugin.settings.data.globalSettings = this.globalSettings;
			this.plugin.saveSettings();
		} catch (err) {
			console.error("Error saving settings:", err);
		}
	}
1 Like

I think by now, after doing some research I have tried to improve my code. So, ignoring all my previous questions from my main post. To put it in simple words, I just wanted to understand one thing :

When i read the settings data using plugin.settings.<AnyKey> or by basically calling the loadSettings function from the main.ts. From where do i receive the data, is it from RAM (after it has loaded from the disk at obsidian startup) or is it loads from disk(data.json) every time i call it ?

Because I was thinking a solution to use sessionStorage, in which i can load at Obisidian Startup or whenever the settings data is changed by the user. And now I can read the data from sessionStorage at whatever speed i want and as many times I want.

Sounds like the issue is with the code in your SettingTab. When you modify the value, you should be doing 2 things: modifying the in-memory settings object, and saving the new settings to disk.

Your plugin should always be accessing the settings object that’s in memory, which will always have the latest value.

Yeah, I have solved that issue now. Actually i was not properly updating the new values (Changed by user from SettingsTab) in the in-memory settings. The code I have shared in the comments seems to be working now.

Since you mention now about in-memory, what does it actually means. Does it means, that when i will be accesing the settings data using plugin.settings.<AnyKey>, is it sent to my plugin from RAM by Obsidian ?

That is, I just want to make sure that, whenever i will be trying to access any value using plugin.settings.<AnyKey> there shouldnt be any read operation to disk.

Obsidian isn’t doing anything magical here. settings is an instance variable, and you are accessing the instance variable to get and set your settings values. Nothing is getting written to or read from disk unless you specially call loadData.

1 Like

Got it ! That was only my main concern, whether accessing plugin.settings was loading data similar to the loadData. Thank you for the quick reply otherwise it would have required me to go through Obsidian Codebase.

Also this is the Solution for my First Question. This code seems to be working fine.

The only thing which i am not sure is a good coding practice is that, now to access the settings, it will require me to pass my plugin instance to all the files. Because I have utils functions which are in a separate file. So right from the main.ts file, i will have to pass the plugin instance all the way upto, somewhere around 7 to 8 levels down, from function to function.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.