當用 autorun
時,函數會被當即執行一次,而後每當它的依賴有任何改變,autorun
都會執行一次。react
生成 name
api
判斷 opts
上是否有 scheduler
和 delay
。若是都沒有,則爲 true
,不然爲 false
。函數
runSync 爲 truethis
實例化 Reaction
,傳入 name
、onInvalidate
函數和錯誤處理函數。spa
reaction = new Reaction(
name,
function(this: Reaction) {
this.track(reactionRunner);
},
opts.onError
);
複製代碼
runSync 爲 falsecode
根據傳入參數,生成本身的調度 scheduler
函數server
實例化 Reaction
,傳入 name
、onInvalidate
函數和錯誤處理函數。對象
reaction = new Reaction(
name,
() => {
if (!isScheduled) {
isScheduled = true;
scheduler(() => {
isScheduled = false;
if (!reaction.isDisposed) reaction.track(reactionRunner);
});
}
},
opts.onError
);
複製代碼
把 this
添加到全局的待處理列表 pendingReactions
中事件
開始執行 runReactions
事務
判斷當前全局中是否處於處理事務狀態或處理反應 reactions
階段,若是是則返回,什麼都不作。不然執行 reactionScheduler(runReactionsHelper)
,也就是執行 runReactionsHelper
if (globalState.inBatch > 0 || globalState.isRunningReactions) return
reactionScheduler(runReactionsHelper)
複製代碼
把全局狀態中 isRunningReactions
設爲 true
,經過 pendingReactions
取到全部待處理 Reaction
實例,並清空 pendingReactions
列表
遍歷全部實例,針對每個實例都調用其自身的 runReaction
,遍歷結束後把全局 isRunningReactions
改成 false
runReaction() {
// 當前是否已經清除
if (!this.isDisposed) {
// 開始處理事務,設置 global.inBatch,令其值 +1
startBatch()
this._isScheduled = false
// 判斷是否須要追蹤,當前 dependenciesState 處於 NOT_TRACKING,shouldCompute 會對於此狀態返回 true
if (shouldCompute(this)) {
// 改變當前狀態
this._isTrackPending = true
try {
// 執行傳遞進來的函數
this.onInvalidate()
// 判斷當前 _isTrackPending 狀態和全局監聽器 spy,若是有全局監聽器,則發送事件,類型爲 scheduled-reaction
if (this._isTrackPending && isSpyEnabled()) {
// onInvalidate didn't trigger track right away..
spyReport({
name: this.name,
type: "scheduled-reaction"
})
}
} catch (e) {
// 錯誤處理
this.reportExceptionInDerivation(e)
}
}
// 結束處理事務
endBatch()
}
}
複製代碼
執行 track
函數,參數爲 reactionRunner
。
// api/autorun.ts
function(this: Reaction) {
this.track(reactionRunner);
}
// core/reaction.ts
function track(fn){
startBatch()
...
const result = trackDerivedFunction(this, fn, undefined)
...
}
// core/derivation.ts
function trackDerivedFunction(derivation, f, context){
...
result = f.call(context)
...
bindDependencies(derivation)
}
複製代碼
startBatch
,再次使 global.inBatch
值 +1
spy
,有則發送事件,類型爲 reaction
,並記錄當前時間_isRunning
爲 true
dependenciesState
爲 UP_TO_DATE
,UP_TO_DATE
意味着值是新的observing
屬性值,若是有值,則遍歷,把每一項的 lowestObserverState
都設爲 UP_TO_DATE
derivation
設置到全局對象上,同時給 derivation
新增屬性globalState.disableErrorBoundaries
,調用傳入的函數,收集新的依賴trackingDerivation
恢復原狀onBecomeStale
,更新全部的依賴項this.isDisposed
判斷須要清除 autorun
reaction
和 derivation
耗時