Javascript 如何在高度规范化的存储库中显示书籍章节中的内容

Javascript 如何在高度规范化的存储库中显示书籍章节中的内容,javascript,mongodb,typescript,google-cloud-firestore,Javascript,Mongodb,Typescript,Google Cloud Firestore,下面的函数有什么问题,我如何修复它 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,

下面的函数有什么问题,我如何修复它

  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])))));
  }
问题是这个函数的返回值。我不想维护它,不想为它编写类型,不想为渲染遍历它等等。它看起来很麻烦,我如何才能抽象它或使它更简单

这是我的模式:

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
}

答:这太可怕了,没有人会想阅读或修改这样写的代码,除非他们想折磨自己谋生

下面的代码稍微更易于维护,主要是通过避免使用承诺的圣诞树和给东西起不同的名字,尽管您必须让类型与您的类型更好地对齐,并且可能会将这些循环步骤中的一些提升到它们自己的功能中来完成这项工作

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];
    }
  }
}

type Id=string;
接口条目{
id:id;
}
接口文档{}
接口BookRepo{
全部:()=>承诺;
部分:(id:id)=>承诺;
章节:(id:id)=>承诺;
内容:(id:id)=>承诺;
}
类列表器{
构造函数(只读bookRepo:bookRepo){}
异步列表(){
const{all,contents,sections,chapters}=this.bookRepo;
const allBooks=等待全部();
for(所有账簿的常量账簿记录){
const bookContents=等待内容(bookRecord.id);
const chapterRecords=等待章节(bookRecord.id);
const bookChapters=等待承诺(
chapterRecords.map(异步(chapterRecord)=>{
const chapterContents=等待内容(chapterRecord.id);
const chapterSectionRecords=等待节(chapterRecord.id);
const chapterSections=等待承诺(
chapterSectionRecords.map(异步(sectionRecord)=>{
const sectionContents=等待内容(sectionRecord.id);
返回[sectionRecord,sectionContents];
})
);
返回[chapterRecord,chapterContents,chapterSections];
})
);
返回[bookRecord,bookContents,bookChapters];
}
}
}

请参见本页。除了很难阅读之外,它还有什么问题?它在干什么?你不想它干什么?基于您的需求,它应该做什么?这与原始代码没有什么不同,只是模型类型是错误的。