摘要:場景和問題這幾天在寫一個。因為狀態的改變由另一個插件控制,不在的中。前者強制觸發一次,后者讓一段代碼執行完成后觸發。所以直接在回調中使用就可以解決問題。參考資料對異常的描述。這種異常附帶在線文檔的方式還是很方便的。
TL;DR
這是一個關于 $rootScope:inprog 錯誤在什么樣的情況下被觸發,和如何解決的故事。
場景和問題這幾天在寫一個 service 。這個 service 中有個狀態需要注入到 directive 中做頁面展現。因為狀態的改變由另一個插件控制,不在 Angular 的 event loop 中。為了觸發 dirty-checking 我在 service 中調用了 $rootScope.$digest() 。
service 代碼大概如下所示:
const STATUS = { A: "A", B: "B", } class SomeService { constructor($rootScope) { this.$rootScope = $rootScope } start() { this.plugin = initPlugin // Register plugin callbacks this.plugin.onStateA = () => { this._setStatus(STATUS.A) } this.plugin.onStateB = () => { this._setStatus(STATUS.B) } } _setStatus(status) { this.status = status this.$rootScope.$digest() } } angular.module("app.someMod").service("someService", SomeService)
目前為止一切正常,直到因為需求改動,需要加一個狀態,這個狀態的改變是通過 directive 中的按鈕觸發的,于是我在 service 中加了一個方法,在 directive 中調用,代碼如下:
// In service class someService { connect() { this._setStatus(STATUS.C) } } // In directive, the "btnClick" is bound to an element"s ng-click scope.btnClick = () => { someService.connect() }
然后一點擊按鈕,程序就跪了…… 控制臺中報的錯誤是 $rootScope:inprog 。
解決方法這段錯誤的官方描述如下:
At any point in time there can be only one $digest or $apply operation in progress. This is to prevent very hard to detect bugs from entering your application. The stack trace of this error allows you to trace the origin of the currently executing $apply or $digest call, which caused the error.
簡單來說,$digest 和 $apply 是用來觸發 dirty-checking 的方法。前者強制觸發一次 dirty-checking ,后者讓一段代碼執行完成后觸發 dirty-checking 。但是 Angular 一次只允許一個 $digest 或者 $apply 運行。上面例子里的代碼會掛,是因為 scope.btnClick 本身已經在 $apply 中執行了,但 someService.connect 內部通過 _setStatus 又調用了一次 $digest ,這就觸發了兩次。
這讓我反思為什么要手動調用 $digest ?其實我的目的只是確保所有狀態改變都觸發 dirty-checking 。因為這個 service 中哪些代碼不會觸發 dirty-checking 是很明確的,那就是插件回調。所以直接在回調中使用 $apply 就可以解決問題。
修改后的代碼如下:
// In service start() { // Wrap code in $apply this.plugin.onStateA = () => { this._wrapStatusChange(STATUS.A) } this.plugin.onStateB = () => { this._wrapStatusChange(STATUS.B) } } connect() { // Change status directly this.status = STATUS.C } _wrapStatusChange(status) { this.$rootScope.$apply(() => { this.status = status }) }總結
只在必要的時候使用 $apply 處理那些不會觸發 dirty-checking 的代碼。大部分的時候 $digest 都可以被 $apply 取代。
參考資料$rootScope:inprog
Angular 對異常的描述。這種異常附帶在線文檔的方式還是很方便的。順帶一提 React 的異常信息也是這樣。
$rootScope.Scope
Scope 的 API ,里面可以查到 $digest 和 $apply 的詳細解釋。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79065.html
摘要:最近在公司使用用完成了一個項目,在此記錄一下過程中遇到的問題及解決方案。其他兩種方法可參考站內文章控制器如何通信結語以上為我在編寫一個應用時遇到的問題及解決方案,記錄并分享出來,歡迎大家指正 最近在公司使用用AngularJS(1.3.9)完成了一個項目,在此記錄一下過程中遇到的問題及解決方案。 使用$http服務發送ajax請求時后端無法判斷請求是XMLHttpRequest 問題...
摘要:年,社區已經擁有萬開發者工作在萬個代碼庫中。這張地圖近似的顯示哪個大陸使用最多。自年月共有萬個公共和私有的拉取請求被合并。今年的拉取請求比去年增加了。多年來,我們已經舉辦了數百個活動,并與世界各地的非營利組織建立了伙伴關系。 本文原創首發于公眾號:ReactNative開發圈,轉載需注明出處。 數百萬的開發者使用GitHub來分享代碼和打造企業。你來此的目的不僅是完成你的工作,獲取新...
摘要:裝飾器我們為啥要討論元素注入器而不是裝飾器這是因為會把元素注入器依賴解析過程限制在當前組件視圖內。但是一旦使用了裝飾器,整個依賴解析過程就會在第一階段完成后停止解析,也就是說,元素注入器只在組件視圖內解析依賴,然后就停止解析工作。 原文鏈接:A curious case of the @Host decorator and Element Injectors in Angular 我...
摘要:基于的版本和編寫的模仿原生應用的源碼地址歡迎項目演示地址建議直接添加到主屏幕端體驗差一些前言為什么做這個項目學習全家桶,很長一段時間在用。作者聲稱之后增強了對的支持,探究在中的支持情況。 vue-ts-daily 基于Vue.js的2.5.13版本和TypeScript編寫的模仿原生應用的WebApp.源碼地址 歡迎star 項目演示地址 showImg(https://segment...
摘要:表格底部的減速幾何平均是一項總的性能指標,從左至右,依次表明了各個框架的評級。最左端是,表示無框架的實現,做為一個參考點。和都是顯著偏慢的框架,兩者給出的性能數據也相差無幾。 文章系國內領先的 ITOM 管理平臺供應商 OneAPM 編譯呈現。 網頁性能是一個豐富且又復雜的話題。在本帖中,我們會將討論的范圍局限在前端 JavaScript 框架上,探究相對于另外一種框架而言,使用當前的...
閱讀 1561·2021-11-24 09:39
閱讀 1042·2021-11-22 15:11
閱讀 2167·2021-11-19 11:35
閱讀 1627·2021-09-13 10:37
閱讀 2453·2021-09-03 10:47
閱讀 2134·2021-08-30 09:47
閱讀 1626·2021-08-20 09:39
閱讀 2901·2019-08-30 14:13