react 的排程,採用優先順序排程(priority),**量大且複雜,看了下 fre 中的排程實現(最短剩餘時間優先),比較精簡且適合快速學習。
問題產生:gui渲染執行緒與js引擎是互斥的,所以需要避免 js 長時間占用導致頁面繪製卡頓。
排程核心:頻繁發起乙個巨集任務,根據事件迴圈機制避免 js 長時間占用(這裡需要 fiber 的架構模式)。
**實現:
這是排程的所有邏輯,短小精悍,核心邏輯和 react 中幾乎一致。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) =>
上面有個問題是 next 的獲取,next如何還存在則繼續執行next,證明 cpu 擁擠,元件沒有渲染完成。如果 next 沒有了證明這個任務渲染完成要出隊,然後再去取最小時間的任務繼續執行。這裡**展示解答一下:
排程入口(react 中的實現):function workloopconcurrent()
}
看下 fre 的精簡實現:function ensurerootisscheduled()
function performconcurrentworkonroot(root, didtimeout)
...}
來張圖輔助理解:export const dispatchupdate = (fiber?: ifiber) =>
const reconcilework = (wip, timeout: boolean): boolean =>
總之,排程解決的問題就是要避免 js 長時間占用導致頁面繪製卡頓,其他問題暫不分析。
react原始碼分析
哪些句子一眼就深入人心?
no1 我以為愛情可以填滿人生的遺憾。然而,製造更多遺憾的。卻偏偏是愛情。no2 原來,愛乙個人,就是永遠心疼她,永遠不捨得責備她。看到她哭,自己的心就跟針扎一樣 看到她笑,自己的就跟開了花兒一樣。在愛情中,每個人都有自己致命的軟肋。no3 你說你懂得生之微末,我便做了這壯大與你看。你說再熱鬧也最終...
想偷懶的時候就來看一眼
多少人,出於恐懼技術的心理,還沒開始就放棄了 多少人,終於開始了,弱弱地堅持卻最終敗給了懶惰 多少人,戰勝了懶惰,卻苦於沒有正確的方法 多少人,迷茫地堅持,卻看不清未來的方向 本人,網際網路行業測試工程師一枚,為了更好的學習測試,開始學習程式設計,通過一段時間的摸爬滾打,總結出幾點心得,比較零散的隨...
你,來到大學的第一眼
快兩年了吧。一年零九個月前,十多個小時的長途夜車,來到了這片廣闊而陌生的土地。第乙個撥打的是你的號碼。好,我現在在上課,你等一下,我就過去。隨後,一位位正裝筆挺的儼然老師模樣的 大傢伙 陸續出現。詢問一番後,找到了你,剛開始還以為這就是即將帶領我們的老師呢?那麼一本正經,一會兒叫填資訊,一會兒讓繼續...