Tips for organizing content within a book chapter and sections within a meticulously structured database

Can you identify the issue with the function below? How would you suggest fixing it?

  list() {
    return this.bookRepo.all().then(books =>
      Promise.all(books.map(book =>
        Promise.all([
          this.bookRepo.contents(book.id),
          this.bookRepo.chapters(book.id)
        ]).then(([contents, chapters]) =>
          Promise.all(chapters.map(chapter =>
            Promise.all([
              this.bookRepo.contents(chapter.id),
              this.bookRepo.sections(chapter.id)
            ]).then(([contents, sections]) =>
              Promise.all(sections.map(section =>
                this.bookRepo.contents(section.id).then(contents => [
                  section, contents
                ])))
                .then(sections => [chapter, contents, sections]))))
            .then(chapters => [book, contents, chapters])))));
  }

The function above seems complex and difficult to maintain. How can we simplify it or make it more abstract?

This is the schema being used:

type BookId = string
type ChapterId = string
type SectionId = string
type ContentId = string

export type SourceId =
| ChapterId
| SectionId
| BookId

type Book = {
  id: BookId,
  name: string,
}

type Chapter = {
  id: ChapterId,
  bookId: BookId,
  name: string
}
type Section = {
  id: SectionId,
  chapterId: ChapterId,
  name: string
}

type Content = {
  id: ContentId,
  name: string,
  sourceId: SourceId,
  content: string
}

Answer №1

Answer: The code provided is extremely convoluted and would deter any sane individual from attempting to read or modify it, unless they enjoy subjecting themselves to unnecessary suffering.

A slightly more manageable approach involves simplifying the structure, avoiding nested promises, utilizing clearer variable names, ensuring proper type alignment, and potentially extracting some logic into separate functions for improved readability.

type Id = string;

interface Entry {
  id: Id;
}

interface Doc {}

interface BookRepo {
  all: () => Promise<Array<Entry>>;
  sections: (id: Id) => Promise<Array<Entry>>;
  chapters: (id: Id) => Promise<Array<Entry>>;
  contents: (id: Id) => Promise<Doc>;
}

class Lister {
  constructor(readonly bookRepo: BookRepo) {}

  async list() {
    const { all, contents, sections, chapters } = this.bookRepo;
    const allBooks = await all();

    for (const bookRecord of allBooks) {
      const bookContents = await contents(bookRecord.id);
      const chapterRecords = await chapters(bookRecord.id);
      const bookChapters = await Promise.all(
        chapterRecords.map(async (chapterRecord) => {
          const chapterContents = await contents(chapterRecord.id);
          const chapterSectionRecords = await sections(chapterRecord.id);
          const chapterSections = await Promise.all(
            chapterSectionRecords.map(async (sectionRecord) => {
              const sectionContents = await contents(sectionRecord.id);
              return [sectionRecord, sectionContents];
            })
          );
          return [chapterRecord, chapterContents, chapterSections];
        })
      );
      return [bookRecord, bookContents, bookChapters];
    }
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

PhantomJS encountered an issue: Attempting to access the 'write' member of a deleted QObject is not allowed

I am in the process of creating a web API on port 7788 that will accept JSON data. This JSON data will then be passed to my API which will render a website. Next, PhantomJS will search for an element on that page and the web API on port 7788 should return ...

"Getting the @connect decorator to integrate seamlessly with redux-saga: a step-by-step guide

What are some effective strategies for combining the use of connect from react-redux as a decorator with redux-saga? import React from 'react'; import { connect } from 'react-redux' @connect(({ data }) => ({ data }), require(' ...

Ways to examine attributes assigned in the controller.$onInit function in AngularJS

In a certain scenario, I am initializing some variables in the controller's $onInit method. How can I verify that these properties are being set correctly? Controller ctrl.$onInit = function () { ctrl.devices = _.cloneDeep(ctrl.formDevices); }; ...

Tips for transferring data between various C# and JavaScript applications

On my ascx page, there is a div element that triggers a JavaScript function when clicked and sends an integer value. //HTML <div style="float: right; margin-right: 150px;" class="innerDivStyle" onclick="userStartExtend(2)"> < ...

Access to PHP script (IF) unattainable following a POST occurrence

I'm completely new at this. I am attempting to create a contact form using HTML5 and PHP mail function, but I am facing an issue with my form action pointing to contacto.php. After submitting the form, it seems to be skipping over the IF condition wi ...

Having trouble with Google font displaying on React site but not on mobile devices?

After importing a Google font that appears perfectly on desktop and cross-browser, an issue arises on mobile where default fonts are shown instead. Below is a snippet from my App.css file: @import url("https://fonts.googleapis.com/css2?family=Turret+Ro ...

Attempting to populate getElementByID using JavaScript function from CodeBehind proves unsuccessful

When a button is clicked on a form, I need to fill in hidden elements that will be posted. The script below should set the values for these hidden fields: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> < ...

What is the best way to modify every instance of a particular item in an array within mongoDB?

Here is the data that I have: { "name": "tom", "songs": [ { "songname": "hello", "day": "20" }, { "songname": "goodbye", "day": &quo ...

setting a value for a nested object in MongoDB

I'm currently facing an issue where I need to update a nested value in my database using the following command: db.getCollection('user'). updateOne( { username: 'adh3', 'pf.acc.accnbr': 1234 } , { "$set": { ...

Nav Bar Toggle Button - Refuses to display the dropdown menus

My Django homepage features a Bootstrap navbar that, when resized, displays a toggle button. However, I am experiencing difficulty with dropdown functionality for the navbar items once the toggle button is activated. Can anyone provide guidance on how to a ...

Issues with the creation of an AngularJS table are causing functionality to malfunction

2021 UPDATE: Note: This question was drafted when I was still learning HTML and JS. If you are seeking assistance for an issue, this might not be very useful as my code was messy. Sorry for any inconvenience caused. The question will remain posted in acco ...

Displaying preprocessing before downloading on the frontend side

Let me walk you through the process first - A user initiates a download request (jsp) Based on the user's parameters (in spring mvc controller mapping), a single excel workbook is created by merging multiple other excel sheets (~40). The final workb ...

`How can I trigger a Child Component method to refresh upon clicking a Button in the Parent Component using Vue JS?`

In a form field within the Parent Component, there is a submit button along with a select option. When the User changes the select option, it should pass that value to trigger a method/function in the child component. I want the child function to be automa ...

Error: zsh is unable to locate the command, even after defining it in package.json bin and installing it globally

I attempted to create a command-line application using TypeScript. Below is the code I have written: //package.json { "name": "jihea-cli", "version": "1.0.0", "description": "", "main": "index.ts", "bin": { "cli": "./bin/index.ts" }, // ...

Upon hitting submit, the form remains unresponsive

I have been developing a permissions system for my NodeJS project (Using the SailsJS MVC) and encountered an issue. After resolving my initial error as detailed here, I am now facing a problem where the form is unresponsive. It neither shows an error in th ...

A guide to showcasing a series of strings in a react element

My aim is to present an array of strings on distinct lines within my React component by utilizing the following code: <div> {this.props.notifications.join('\n')} </div> Nonetheless, it appears that this a ...

What could be causing the issue with my validation for alphabetical input?

I am currently working on a registration form that only accepts alphabetical input. However, I am facing an issue where my error message appears regardless of whether I input an alphabetical or special character. According to my understanding, the code sho ...

"The reactivity of VueJs array of objects is not triggering properly when there is a change in

My state includes an array of objects structured like this: data() { return { users: [{id: 1, name: 'bob'}, {id: 2, name: 'bill'}] } } After modifying the data as shown below: this.users[0].name = 'Mary' The watc ...

The StrongLoop ng-lb command encounters issues when utilizing the local-storage-connector

Hello Strongloop community, I have been experimenting with the local-storage data store example provided by loopback. It's working well and I can successfully create and retrieve files from the local file system (used as a data source) using the REST ...

Exposed function in JavaScript vulnerable to exploitation

In my application, I have a JavaScript function that redirects users to the login page after a minute: (function redirect_expired() { $j.get('/app/ExpiredSession', function (resp) { if (resp && resp.redirectTo) { ...