Many sync callbacks should support async overloads

For example

// in class Vault
process(file: TFile, fn: (data: string) => string, options?: DataWriteOptions): Promise<string>;

we need to allow async overloads

process(file: TFile, fn: (data: string) => string | Promise<string>, options?: DataWriteOptions): Promise<string>;

Similarly,

processFrontMatter(file: TFile, fn: (frontmatter: any) => void | Promise<void>): Promise<void>;

Currently to add such functionality we have to build our own workarounds

These APIs being synchronous is on purpose; it is to prevent race conditions from modifying the file in between your read + write call. If they were asynchronous then it would defeat the purpose.

In your use case, if you need asynchronous versions, then you can just use something like this:

let content = await vault.read(file);
// Do asynchonous processing
let newContent = await myAsyncProcess(content);
// Call API
vault.process(file, (data) => {
    // Making sure the data hasn't changed since you read the file
    if (data === content) {
        return newContent;
    }
    else {
        // File has been modified while you were processing things asynchronously
        // Best thing to do here is either to throw an error, or try again.
        throw new Error('File has been modified');
    }
});
2 Likes

@Licat thanks that’s very similar to what I already have in my helpers. However I think it would be friendlier for API users if you add such logic to your API.

Additionally you can add a parameter

overwriteOnRaceCondition: boolean
    if (overwriteOnRaceCondition || data === content) {
        return newContent;
    }
    else {
        throw new Error('File has been modified');
    }