MobX computed - согласование цепочки вычисленных значений
У меня есть три связанных вопроса о лучших практиках с "computed".
TL; DR: Что мне нужно думать о себе и что делать примирение из коробки.
Допустим, я загружаю здоровенный набор данных в переменную данных:
data = asyncComputed( await fetch … return data )
У меня тогда есть удобная вычисленная опора, которая форматирует эти данные:
@computed get timeseries() {
const data = this.data.get()
const timeseries = nest()
.key(d => d.geo)
.entries(data)
return timeseries
}
И третья удобная опора, рассчитанная на верхнюю часть временных рядов:
@computed get extentX() {
const timeseries = this.timeseries.get()
const extentX = extent(timeseries, d => d.time)
return extentX
}
Существует ли риск того, что рендеринг произойдет до того, как будут выполнены все эти вычисления, или MobX гарантирует, что это было согласовано раньше?
Есть ли лучший способ структурирования этого кода, чтобы избежать цепочки вычисляемых реквизита?
Допустим, первая асинхронная синхронизация запускается, когда свойство (id) изменяется для объекта, и этот объект позднее обновляется из той же цепочки событий:
variable = { id : “my-variable”, extent: undefined}
data = asyncComputed( await fetch api?id=variable.id )
=> вычисляет экстент => приводит к переменной.extent = [200, 400] Есть ли риск, что это может вызвать бесконечный цикл, или безопасно обновить свойство объекта, подобное этому?
1 ответ
Вот мои мысли на эту тему.
- Mobx Запускает все вычисления синхронно ( Prof см. Синхронное выполнение)
- Mobx делает ленивую оценку ( Проф см. Ленивый против реактивной оценки)
- При подаче заявления
@observer
он просто оборачивает функцию рендеринга вautorun
( Доказательство)
Из #1 мы можем сделать вывод, что если у нас есть цепочка вычислений, они оцениваются синхронно, как: observable -> computed 1 -> computed 2
Из #2 можно сказать, что для запуска побочного эффекта - эта вычисленная цепочка должна заканчиваться автозапуском observable -> computed 1 -> computed 2 -> autorun
Это уже приводит нас к пункту № 3. Тот @observer
это HOC, который оборачивает ваш Компонент и контролирует всякий раз, когда он должен быть перерисован. Теперь это не находится под контролем вашего компонента.
Итак, отвечая на ваши вопросы:
- Нет риска, что рендеринг произойдет между вычисленными вычислениями. Это будет после последнего
computed
позвонюautorun
- Цепочка
computed
это мощный подход, и его не следует избегать, просто используется мудро.
Из документов:
Составляя реактивные вычисления, можно даже автоматически преобразовать один граф данных в другой граф данных и поддерживать этот вывод в актуальном состоянии с минимальным количеством исправлений. Это облегчает реализацию сложных шаблонов, таких как уменьшение карты, отслеживание состояния с использованием неизменяемых общих данных или боковой загрузки данных.
- Моб имеет защиту от петель. Вы увидите консольную ошибку, что изменение наблюдаемых, которые вызвали поток, не допускается
По моему опыту, построение "вычисляемых" значений MobX поверх других "вычисленных" значений является простым и надежным, и это очень мощный способ разбить сложные преобразования данных на логические и проверяемые детские шаги.
При использовании серии "вычислений" каждый шаг представляет собой преобразование данных, основанное на предыдущих результатах, и каждый шаг имеет имя. Таким образом, результатом каждого шага является именованный наблюдаемый объект, который ваше приложение может просматривать или отображать на экране. Это упрощает написание, тестирование и отладку каждого шага отдельно.
Во время выполнения ваши "вычисления" верхнего уровня получают такую же магическую эффективность и повторные вычисления, что и простые "вычисления", так что на самом деле нет никаких недостатков. Я очень рекомендую это.