一眼就懂的 React 排程演算法

2021-10-25 14:20:46 字數 1924 閱讀 2568

react 的排程,採用優先順序排程(priority),**量大且複雜,看了下 fre 中的排程實現(最短剩餘時間優先),比較精簡且適合快速學習。

問題產生:gui渲染執行緒與js引擎是互斥的,所以需要避免 js 長時間占用導致頁面繪製卡頓。

排程核心:頻繁發起乙個巨集任務,根據事件迴圈機制避免 js 長時間占用(這裡需要 fiber 的架構模式)。

**實現:

const queue = 

// react中為 5ms,fre中為16ms 是多少目前看無所謂

const threshold = 1000 / 60

const unit =

let deadline = 0

// 收集 flushwork 並觸發乙個巨集任務

export const schedule = (cb) => unit.push(cb) === 1 && postmessage()

// 對外暴露的入口,進行任務收集

export const schedulework = (callback, time) =>

queue.push(job)

schedule(flushwork)

}// 不相容 messagechannel 則使用 settimeout

const postmessage = (() => = new messagechannel()

port1.onmessage = cb

return () => port2.postmessage(null)

} return () => settimeout(cb)

})()

// 這裡執行傳入的任務

const flush = (inittime) => else

job = peek(queue)

currenttime = gettime()

} return !!job

}// 還有任務一直遞迴執行

const flushwork = () =>

// 是否過期

export const shouldyield = () =>

export const gettime = () => performance.now()

// 最短剩餘時間優先執行(react根據優先順序進行的過期時間排序)

const peek = (queue) =>

這是排程的所有邏輯,短小精悍,核心邏輯和 react 中幾乎一致。

上面有個問題是 next 的獲取,next如何還存在則繼續執行next,證明 cpu 擁擠,元件沒有渲染完成。如果 next 沒有了證明這個任務渲染完成要出隊,然後再去取最小時間的任務繼續執行。這裡**展示解答一下:

function workloopconcurrent() 

}

排程入口(react 中的實現):

function ensurerootisscheduled()

function performconcurrentworkonroot(root, didtimeout)

...}

看下 fre 的精簡實現:

export const dispatchupdate = (fiber?: ifiber) => 

const reconcilework = (wip, timeout: boolean): boolean =>

來張圖輔助理解:

總之,排程解決的問題就是要避免 js 長時間占用導致頁面繪製卡頓,其他問題暫不分析。

react原始碼分析

哪些句子一眼就深入人心?

no1 我以為愛情可以填滿人生的遺憾。然而,製造更多遺憾的。卻偏偏是愛情。no2 原來,愛乙個人,就是永遠心疼她,永遠不捨得責備她。看到她哭,自己的心就跟針扎一樣 看到她笑,自己的就跟開了花兒一樣。在愛情中,每個人都有自己致命的軟肋。no3 你說你懂得生之微末,我便做了這壯大與你看。你說再熱鬧也最終...

想偷懶的時候就來看一眼

多少人,出於恐懼技術的心理,還沒開始就放棄了 多少人,終於開始了,弱弱地堅持卻最終敗給了懶惰 多少人,戰勝了懶惰,卻苦於沒有正確的方法 多少人,迷茫地堅持,卻看不清未來的方向 本人,網際網路行業測試工程師一枚,為了更好的學習測試,開始學習程式設計,通過一段時間的摸爬滾打,總結出幾點心得,比較零散的隨...

你,來到大學的第一眼

快兩年了吧。一年零九個月前,十多個小時的長途夜車,來到了這片廣闊而陌生的土地。第乙個撥打的是你的號碼。好,我現在在上課,你等一下,我就過去。隨後,一位位正裝筆挺的儼然老師模樣的 大傢伙 陸續出現。詢問一番後,找到了你,剛開始還以為這就是即將帶領我們的老師呢?那麼一本正經,一會兒叫填資訊,一會兒讓繼續...