Last active
June 25, 2019 12:23
-
-
Save WeiGrand/f4d6255a371356485ed6d79a40e36083 to your computer and use it in GitHub Desktop.
Fiber (虚拟栈实现)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const a1 = {name: 'a1', child: null, sibling: null, return: null}; | |
const b1 = {name: 'b1', child: null, sibling: null, return: null}; | |
const b2 = {name: 'b2', child: null, sibling: null, return: null}; | |
const b3 = {name: 'b3', child: null, sibling: null, return: null}; | |
const c1 = {name: 'c1', child: null, sibling: null, return: null}; | |
const c2 = {name: 'c2', child: null, sibling: null, return: null}; | |
const d1 = {name: 'd1', child: null, sibling: null, return: null}; | |
const d2 = {name: 'd2', child: null, sibling: null, return: null}; | |
a1.child = b1; | |
b1.sibling = b2; | |
b2.sibling = b3; | |
b2.child = c1; | |
b3.child = c2; | |
c1.child = d1; | |
d1.sibling = d2; | |
b1.return = b2.return = b3.return = a1; | |
c1.return = b2; | |
d1.return = d2.return = c1; | |
c2.return = b3; | |
/** | |
* a1 --- | |
* | | |
* | | |
* b1 | |
* | | |
* | | |
* b2 --- | |
* | | | |
* | | | |
* | c1 --- | |
* | | | |
* | | | |
* | d1 | |
* | | | |
* | | | |
* | d2 | |
* b3 --- | |
* | | |
* | | |
* c2 | |
*/ | |
// workInProgress 当前用遍历的 Fiber 树 | |
const log = console.log; | |
let nextUnitOfWork = a1; | |
// performUnitOfWork -> beginWork -> completeUnitOfWork -> completeWork | |
const workLoop = () => { | |
while (nextUnitOfWork !== null) { | |
nextUnitOfWork = performUnitOfWork(nextUnitOfWork); | |
} | |
} | |
/** | |
* 用来遍历 Fiber 节点 | |
* 深度优先访问子节点 | |
* 子节点为空则开始执行 work | |
* @param workInProgress | |
* @returns {*} | |
*/ | |
const performUnitOfWork = workInProgress => { | |
let next = beginWork(workInProgress); | |
if (next === null) { | |
next = completeUnitOfWork(workInProgress); | |
} | |
return next; | |
} | |
const beginWork = workInProgress => { | |
log('Work performed for ' + workInProgress.name); | |
return workInProgress.child; | |
} | |
/** | |
* 用来执行 work | |
* 执行完 work 看当前节点是否有相邻节点 | |
* 有相邻节点则遍历相邻节点 | |
* 无相邻节点则看是否有父节点 | |
* 有父节点则将 workInProgress 设为 其父节点 | |
* 没有父节点当前已经当了根节点 返回 空 结束循环 | |
* @param workInProgress | |
* @returns {null|*} | |
*/ | |
const completeUnitOfWork = workInProgress => { | |
while (true) { | |
let returnFiber = workInProgress.return; | |
let siblingFiber = workInProgress.sibling; | |
nextUnitOfWork = completeWork(workInProgress); | |
if (siblingFiber !== null) { | |
return siblingFiber; | |
} else if (returnFiber !== null) { | |
workInProgress = returnFiber; | |
} else { | |
return null; | |
} | |
} | |
} | |
const completeWork = workInProgress => { | |
log('Work completed for ' + workInProgress.name); | |
return null; | |
} | |
workLoop(); | |
// Output | |
// Work performed for a1 | |
// Work performed for b1 | |
// Work completed for b1 | |
// Work performed for b2 | |
// Work performed for c1 | |
// Work performed for d1 | |
// Work completed for d1 | |
// Work performed for d2 | |
// Work completed for d2 | |
// Work completed for c1 | |
// Work completed for b2 | |
// Work performed for b3 | |
// Work performed for c2 | |
// Work completed for c2 | |
// Work completed for b3 | |
// Work completed for a1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment