Создайте загрузчик для классов, которые зависят друг от друга

#javascript #angular

Вопрос:

Предположим, у меня есть следующий JSON :

 [{
  "id": "main",
  "deps": [],
  "class": "export class MainClass { constructor() { console.log('I am the main class'); } }"
}, {
  "id": "logger",
  "deps": ["main"],
  "class": "export class MainClass { constructor(main) { console.log('I am the logger : ', main); } }"
}, {
  "id": "feat",
  "deps": ["main", "logger"],
  "class": "export class MainClass { constructor(main, logger) { console.log('I am a feature: ', main, logger); } }"
}]
 

Как вы можете видеть, JSON содержит

  • Идентификатор класса, позволяющий идентифицировать его уникальным способом
  • Список зависимостей для класса, которые вводятся в конструктор
  • Некоторый код для самого класса

Предположим, я уже могу создавать классы и вводить их зависимости в правильном порядке.

Моя проблема в том, что :

Как я могу построить классы в правильном порядке, чтобы каждая зависимость загружалась правильно ?
(Другими словами, как отсортировать этот массив в правильном порядке)

Мой первоначальный подход состоял в том, чтобы дать «уровень» каждому классу в зависимости от их количества зависимостей. Но это не гарантирует порядок, следовательно, зависимости не определены …

Любая помощь будет очень признательна !

PS : Я использую Angular, отсюда и теги, я не знаю, что еще добавить, поэтому, если я неправильно поставил вопрос, не стесняйтесь редактировать его

ОТРЕДАКТИРУЙТЕ Вот MCVE, чтобы помочь вам протестировать его :

 const classes = [{
    id: "main",
    deps: [],
    class: "class MainClass { constructor() { console.log('I am the main class'); } }",
  },
  {
    id: "logger",
    deps: ["main"],
    class: "class MainClass { constructor(main) { console.log('I am the logger : ', main); } }",
  },
  {
    id: "feat",
    deps: ["main", "logger"],
    class: "class MainClass { constructor(main, logger) { console.log('I am a feature: ', main, logger); } }",
  },
  {
    id: "levelIssue",
    deps: ["feat"],
    class: "class levelIssueClass { constructor(feat) { console.log('I depend on feature : ', feat); } }",
  },
];

// This is the variable that should have everything sorted
const ordered = classes.sort((a, b) => a.deps.length - b.deps.length);

const instanciated = {};

for (const c of ordered) {
  eval('window.module = '   c.class);
  const deps = c.deps.map(id => instanciated[id]);
  const tmp = new window.module(...deps);
  instanciated[c.id] = tmp;
  delete window.module;
} 

Ответ №1:

Ну, в вашем примере у вас вроде как уже есть «уровень» для каждого класса, если вы рассматриваете deps.length свойство.

Поэтому, если вы сначала загружаете все свои классы без зависимостей ( deps: [] ), То после классов с одной зависимостью и так далее вам просто нужно отсортировать массив таким образом.

[РЕДАКТИРОВАТЬ] Прежде чем вы это сделаете, вы должны сопоставить свой deps , чтобы получить весь список, чтобы класс был на правильном уровне, прежде чем вы выполните загрузку.

Это выглядело бы примерно так:

 const data = [{
    id: "main",
    deps: [],
    class: "class MainClass { constructor() { console.log('I am the main class'); } }",
  },
  {
    id: "logger",
    deps: ["main"],
    class: "class MainClass { constructor(main) { console.log('I am the logger : ', main); } }",
  },
  {
    id: "feat",
    deps: ["main", "logger"],
    class: "class MainClass { constructor(main, logger) { console.log('I am a feature: ', main, logger); } }",
  },
  {
    id: "levelIssue",
    deps: ["feat"],
    class: "class levelIssueClass { constructor(feat) { console.log('I depend on feature : ', feat); } }",
  },
];

// map dependencies
const classes = data.map((item) => {
  // gets the dependencies from dependencies and concats into one array
  const deps = item.deps.concat(item.deps.map(classId => data.find(c => c.id === classId).deps)).flat();
  return {
     ...item,
     deps,
  }; 
});

// sort by deps.length
classes.sort((a, b) => (a.deps.length > b.deps.length) ? 1 : -1).forEach((item) => {
  // load item
});
 

Комментарии:

1. Привет, спасибо за ваше предложение, к сожалению, оно работает не так, как задумывалось. Я отредактировал исходное сообщение, чтобы добавить новый класс с одной зависимостью, которая зависит от класса с двумя : зависимость становится неопределенной. Я также добавил MCVE, если вы хотите его протестировать !

2. Я отредактировал свой ответ с предложением карты, проверьте, соответствует ли он вашим потребностям сейчас 🙂