Is there a way to make a code block run/reload on an interval basis?

I have a note in the right sidedbar that embeds sections from another note based on time of day, using dataviewjs. I use this for time-blocking purposes. I need this to be a subtle visual effect rather than, for example, a disruptive pop-up notification, which is why I’ve gone down this route. Here’s a simplified version of the code:

function getTimeBlock() {
	const currentMinute = new Date().getMinutes();
	if (currentMinute < 45) {
		if (currentMinute < 43) {
			return "![[TimeBlocksFile.md#day1]]" + "![[TimeBlocksFile.md#day2]]";
		}
		return "![[TimeBlocksFile.md#day1]]";
	}
	return "![[TimeBlocksFile.md#evening2]]";
}

dv.span(getTimeBlock());

What I’m trying to do

The code works as intended, but the sidebar note only reloads the result if I start manually editing the code block (cursor must be inside the block and I also have to input something, like an extra space). When the note is in the main workspace, it updates when I navigate away from it and come back. Neither result is ideal and I wonder if there’s a way to make this run without my interaction.

Things I have tried

For context, I’m not a programmer so I just approach things based on a hunch, trying to apply methods that seem applicable to my layperson brain.

I tried adding the following at the end of my code, without success:
setInterval(getTimeBlock, 1000);

I changed how I wrote the if statements (to what I posted here) and caught and fixed an error too, but these fixes aren’t giving different results.

I also tried setInterval(getTimeBlock(), 1000); which didn’t help but makes the console throw this error in a loop (a):
Uncaught error: unexpected identifier ‘#evening2

I then asked a piece of AI and it suggested to toggle the note’s edit mode on and off to make it reload. It gave this code:

setInterval(() => { 
	this.app.workspace.activeLeaf.view.sourceMode.toggle();
	this.app.workspace.activeLeaf.view.sourceMode.toggle(); 
}, 1000);

…to which console responds:
Uncaught TypeError: this.app.workspace.activeLeaf.view.sourceMode.toggle is not a function

I decided to not try to fix that because even if I managed to programmatically toggle the source/preview modes, I’m not confident that it would help, as doing the same manually won’t update the file in the sidebar, which is the main feature I’m after.

As far as I can tell, any code in a note is performed one time only. I couldn’t find much information on this forum or the Obsidian documentation, but then again, I don’t know the correct terminology for what I’m looking for, so I may have missed something. Any help would be appreciated!

Update:

I found this loop function description and decided to go with that next.

The following code creates a new embed according to the set interval and they reflect the time correctly. But they are created one after another rather than the existing embed being removed and replaced by the new one. For that reason I already set a class for the span element, but at the moment I’m not sure how to go about replacing it.

(function loop() {
    setTimeout(() => {
        function getTimeBlock() {
            const currentMinute = new Date().getMinutes();
            if (currentMinute < 9) {
                if (currentMinute < 8) {
                    return "![[TimeBlocksFile.md#day1]]" + "![[TimeBlocksFile.md#day2]]";
                }
                return "![[TimeBlocksFile.md#day1]]";
            }
            return "![[TimeBlocksFile.md#evening2]]";
        }
        const embedContent = getTimeBlock();
        const spanElement = dv.span(embedContent);
        spanElement.classList.add("timeblockplace");
        loop();
    }, 3000);
})();

Talking to myself some more here.

I tinkered around with that loop but wasn’t sure what I was doing and tried once more to search for similar topics:

This topic mentions making a button that “edits” the code into what it already was, which will trigger reload. It works but I’m faced with the same question of how to automate pressing the button.

A function to reload Obsidian is mentioned here. I’m guessing it’s the one that this bit of code also uses:

// Automatically refresh the note after a certain interval
setInterval(() => {
  location.reload();
}, 3000); // Refresh every minute (adjust the interval as needed)

I’ve tried to add this to my code block. It reloads the entire Obsidian vault, not just the one note the code is on.

Then there’s this topic that asks how to force refresh but no useful responses.

I’m not sure if what I’m trying to do is simply not doable. I even tried to open the file I want to refresh in TextMate and save it there. Lo and behold, it gets reloaded in Obsidian right away (with slight delay, probably the dataview generic reload time that can be changed in the settings). I don’t even have to edit the file at all; a simple save does the trick.

Current thoughts

Should I learn python to trigger saving the file once every minute whenever Obsidian is running? How much work would that be?

Also: What would be the best place/way to ask for help? Why am I not finding prior discussion on this?

In recent version of Dataview you can call the Dataview: Rebuild current view, which will refresh just the current view. This can be triggered through a call to setInterval() similar to what you’re doing now.

However, there is a caveat that this might trigger multiple concurrent setInterval(), so take a look at the thread below which is a similar case and see if you can’t incorporate some of that logic to keep to only one repeated process.

1 Like

Thanks for the tip @holroy ! I wasn’t aware of Rebuild current view.

I’ve already gone ahead and created a Python script that solved this for my use case (fingers crossed). I noticed that merely changing the file’s modification date without editing the file itself will trigger an updated view. I’m using the same script to update my dashboard page once a day, because it has links to today’s and yesterday’s daily notes that also weren’t automatically updating.

As I don’t actually know what I’m doing, I wouldn’t know which method is better from a system standpoint, but I don’t trust my ability to implement the setInterval code properly, so I’ll go with this for now and see if I run into any trouble with it.