нажмитеВойдите в репозиторий отладки исходного кода React.
Как библиотека JavaScript для создания пользовательских интерфейсов, React фокусируется на улучшении взаимодействия с пользователем.Самый важный момент для достижения этой цели — отдать приоритет реагированию на задачи обновления, вызванные взаимодействием с пользователем, и сделать уступки для других менее важных задач. запущенные задачи называются задачами с высоким приоритетом, а менее важные задачи называются задачами с низким приоритетом.
В режиме Concurrent в React наличие задач с разными приоритетами приведет к явлению:Задачи с высоким приоритетом могут прерывать выполнение задач с низким приоритетом. Но прерывания прерываниями, а низкоприоритетные задачи всегда восстанавливаются, так что,Задачи с низким приоритетом возобновляются после прерывания. Кроме того, еслиЗадачи с низким приоритетом всегда прерываются задачами с высоким приоритетом, затем задачи с низким приоритетом истекают и будут принудительно выполняться. Вот два вопроса, которые мы собираемся обсудить:Высокоприоритетные задачи сокращаются в очередьа такжепроблема голода.
Контроль выполнения задач с разными приоритетами в React имеет только одну цель — предоставить пользователю самые срочные обновления. Я буду обсуждать эти два вопроса в следующих двух статьях. Но прежде чем мы начнем, Сначала нам нужно понять основы управления приоритетами задач React: модель дорожки и то, как она связана с обновлениями React.
Обратите внимание, что приоритет задачи в React, упомянутый в этой статье, — это не то же самое понятие, что и приоритет задачи планировщика в механизме планирования, и последний может быть преобразован из первого.
модель с приоритетом полосы движения
В React 17 модель приоритета была заменена новой моделью дорожки. Модель делит приоритет на 31, что соответствует 31 двоичному биту.
const TotalLanes = 31;
export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b0000000000000000000000000000000;
export const SyncLane: Lane = /* */ 0b0000000000000000000000000000001;
export const SyncBatchedLane: Lane = /* */ 0b0000000000000000000000000000010;
export const InputDiscreteHydrationLane: Lane = /* */ 0b0000000000000000000000000000100;
const InputDiscreteLanes: Lanes = /* */ 0b0000000000000000000000000011000;
const InputContinuousHydrationLane: Lane = /* */ 0b0000000000000000000000000100000;
const InputContinuousLanes: Lanes = /* */ 0b0000000000000000000000011000000;
export const DefaultHydrationLane: Lane = /* */ 0b0000000000000000000000100000000;
export const DefaultLanes: Lanes = /* */ 0b0000000000000000000111000000000;
const TransitionHydrationLane: Lane = /* */ 0b0000000000000000001000000000000;
const TransitionLanes: Lanes = /* */ 0b0000000001111111110000000000000;
const RetryLanes: Lanes = /* */ 0b0000011110000000000000000000000;
export const SomeRetryLane: Lanes = /* */ 0b0000010000000000000000000000000;
export const SelectiveHydrationLane: Lane = /* */ 0b0000100000000000000000000000000;
const NonIdleLanes = /* */ 0b0000111111111111111111111111111;
export const IdleHydrationLane: Lane = /* */ 0b0001000000000000000000000000000;
const IdleLanes: Lanes = /* */ 0b0110000000000000000000000000000;
export const OffscreenLane: Lane = /* */ 0b1000000000000000000000000000000;
Сравнение различных уровней приоритета
Из названия приоритета и соответствующего бита, чем правее, тем выше приоритет. После поступления каждой задачи ее флаг приоритета: полоса будет соответствовать определенному биту.
Например, полоса, занимаемая задачей 1:
0b0000000000000000000001000000000
Переулок, удерживаемый задачей 2: ~~~~
0b0000000000000000000000000001000
Тогда задача 2 имеет более высокий приоритет, чем задача 1.
Принцип расчета полосы
Мы знаем, что всякий раз, когда генерируется обновление, будет сгенерирован объект обновления, и объект обновления будет иметь полосу, указывающую приоритет обновления. Как рассчитывается эта полоса?В относительно фиксированном диапазоне приоритета приоритет отдается битам более высокого уровня, и если указаны все биты дорожек в фиксированном диапазоне, то для указания переходят к битам дорожек соседнего диапазона более низкого уровня..
Например: Событие 1 инициирует обновление A, областью приоритета которого является InputDiscreteLanes,
0b0000000000000000000000000011000
Тогда дорожка обновления А будет обозначена как предпоследний бит в расчете.Если она занята, она будет обозначена как предпоследний пятый бит.Если она все еще занята, она будет перемещена вниз к соседнему низкоуровневому приоритету.
0b0000000000000000000000011000000
Укажите в этом диапазоне.Если диапазон также указан, продолжайте движение вниз и повторяйте этот процесс, пока не найдете доступный бит, назначьте его ему, завершите расчет, поместите его на объект обновления и поместите его в корень .pendingLanes, root.pendingLanes представляют те обновления, которые React должен обработать на этот раз.
Как узнать, следует ли обрабатывать обновление
Как только задача обновления сгенерирована, React начнет строить дерево workInProgress. Перед построением он найдет самые срочные дорожки в root.pendingLanes как renderLanes, а рабочий цикл, который строит дерево workInProgress, уберет эти renderLanes полностью вниз. При обновлении связного списка на файбер-узле будет судить о том, находится ли update.lane в renderLanes в свою очередь, если да, то он будет обработан, иначе не будет обработан.
export function processUpdateQueue<State>(
workInProgress: Fiber,
props: any,
instance: any,
renderLanes: Lanes,
): void {
do {
if (!isSubsetOfLanes(renderLanes, updateLane)) {
// updateLane在renderLanes中,处理这个更新
} else {
// 否则不处理,跳过
}
} while (true);
}
Поскольку расчет дорожек задается сверху вниз, если дорожка не входит в область действия renderLanes, она должна иметь недостаточный приоритет и должна быть пропущена.
резюме
Прежде чем исследовать поведение React при сосуществовании нескольких задач с разными приоритетами, мы кратко рассмотрели взаимосвязь между моделью дорожек и обновлениями. Но модель лейна предполагает множество битовых операций, и сложно понять, когда ее путают с приоритетом, поэтому у меня есть важный документ по расчету лейна в React:ReactFiberLaneСделал несколько комментариев, которые могут помочь в понимании того, как работают дорожки.
В следующих двух статьях будет обсуждаться переключение высокоприоритетных задач и голодание соответственно.