Development of Dendron Import Plugin folders not as expected

Hi All,

Im currently working on a plugin, it will import dendron notes and is based on import-quiver. dendron uses file names folder.folder.folder.notename.md each dot represents a new folder. I have written the below which splits the filename, then loops through each element, if a notebook is found, the id is saved in inkNotebook then when the next element is checked, if a notebook is not found it should create a new one with parentBookId: inkNotebook.

For some reason, when I do this if multiple notebooks are created in a row, they are all created under the same parent even though the inkNotebook variable appears to be updated. Its like the database isnt updating fast enough or something.

image

I also noticed that when looking at the console.log they don’t appear in the order I would expect them to.

there may be a more elegant way to do this, however i’m new to react so still learning.

async function findOrCreateNotebook(noteName) {
  // split  the noteName into folders
  const splitName = noteName.split(".");
  // remove last 2 elements as this is the file name
  const notebookNames = splitName.slice(0, splitName.length - 2);
  // names should only contain folders log to check
  console.log(notebookNames);

  // used to save parent notebook ID
  let inkNotebook;

  // loop through each folder
  notebookNames.forEach(async (name, index) => {
    console.log(`processing folder ${name} id: ${index}`);
    // get local DB store
    const db = inkdrop.main.dataStore.getLocalDB();
    console.log(`all books`, await db.books.all());
    // find if notebook already exists
    return await db.books.findWithName(name).then(async foundNotebook => {
      console.log(`found notebook`, foundNotebook);
     // notebook found, return ID
      if (foundNotebook) {
        inkNotebook = foundNotebook._id;
        return foundNotebook._id;
      }
      // Or, create new note.
      const createdAt = new Date().getTime();
      const updatedAt = new Date().getTime();
      let book
      // if its the first element, no need for a parent id
      if (index === 0) {
        book = new Book({
          name: name,
          createdAt: createdAt,
          updatedAt: updatedAt
        });
      } else {
        console.log(`index: ${index}, parent: ${inkNotebook}`);
        book = new Book({
          name: name,
          createdAt: createdAt,
          updatedAt: updatedAt,
          parentBookId: inkNotebook
        });
      }
      // put the book into the DB and return its  ID
      return await db.books.put(book).then(response => {
        console.log(`Created notebook`, response);
        inkNotebook = response.id

        return response.id;
      });

    });

  });
}

I have tried multiple ways to do this, but this one is the closest I have managed.

Hi Steven,

Thanks for the question.
I looked into your code and found that you call notebookNames.forEach.
I guess it is causing the race condition problem because forEach itself doesn’t wait for each loop regardless of the async function.
Instead, consider replacing it with for...of loop.

Thanks Takuya,

That was the issue, I had two forEach loops, I replaced the one mentioned in the above code, which made things a little better, but also found that I was doing the same again in another part which caused further issues.

Now that I have removed the forEach and used for…of it is working.

Hopefully have this plugin finished soon now :slight_smile:

1 Like

Nice! Glad it solved. Looking forward to seeing your plugin :smiley: