$rootScope:inprog การดำเนินการอยู่ในระหว่างดำเนินการ

ฉันเริ่มทำงานกับ Angular Material และมีปัญหาในการทำความเข้าใจปัญหาเกี่ยวกับฟังก์ชัน $scope.apply... ทุกครั้งที่ฉันพยายามแจ้ง UI เกี่ยวกับการเปลี่ยนแปลงโดยการเรียก apply มันล้มเหลวโดยมีข้อผิดพลาด ฉันรู้ว่ามีคำถามที่คล้ายกันเกี่ยวกับ SO แต่ในกรณีของฉันข้อมูลไม่ได้ถูกจัดเก็บโดย scope แต่โดยอินสแตนซ์ของตัวควบคุม...

ฉันยังใช้ TypeScript สำหรับการใช้งานคอนโทรลเลอร์ของฉันด้วย ไม่แน่ใจ แต่ดูเหมือนว่าจะค่อนข้างแปลก เนื่องจากโค้ดตัวอย่างส่วนใหญ่ที่ฉันพบจะขึ้นอยู่กับการใช้งานคอนโทรลเลอร์แบบอินไลน์ในมุมมอง

คอนโทรลเลอร์ของฉันดูเหมือนว่า...

module MyApp {

    export class MyController {

        private scope: angular.IScope;
        private http: angular.IHttpService;

        public model: { data: SampleData } = { data: { } };

        constructor($scope: angular.IScope, $http: angular.IHttpService) {
            this.scope = $scope;
            this.http = $http;
        }

        public querySampleData(): void {

            const serviceEndpoint: string = "http://localhost:8080/api/";
            var promise: ng.IHttpPromise<SampleData> = this.http.get(serviceEndpoint + "sample", { });

            var callback: ng.IHttpPromiseCallback<SampleData> = (
                data: SampleData,
                status: number,
                headers: angular.IHttpHeaderGetter,
                config: angular.IRequestConfig) => {
                this.scope.apply(() => {
                    this.model.data = data;
                };
            };

            promise.success(callback);
        }
    }

    export interface SampleData {
        message? string;
    }
}

คอนโทรลเลอร์จัดเตรียมเมธอด querySampleData ซึ่งรับข้อมูลบางส่วนจากบริการระยะไกล (ใช้ IHttpService สำหรับการเรียก API แบบอะซิงโครนัส) มุมมองจะใช้คอนโทรลเลอร์ในลักษณะดังต่อไปนี้...

<html ng-app="app">
    <body ng-controller="MyController as c">
        <div>
            <button ng-click="c.querySampleData()" 
                    aria-label="Query sample data">Query sample data</button>
            <p>{{c.model.data.message}}</p>
        </div>
        ...
        <script src="../scripts/app.js"></script>
        <script type="text/javascript">
            var app = angular.module("app", ["ngMaterial"]);
            app.controller("MyController", [ "$scope", "$http", MyApp.MyController ]);
        </script>
    </body>
</html> 

การเริ่มต้นคอนโทรลเลอร์ทำงานได้ดี การขึ้นต่อกันทั้งหมดจะถูกฉีดเข้าไปในคอนโทรลเลอร์อย่างถูกต้อง และการโยงกับเมธอด querySampleData ก็ทำงานได้ตามที่คาดไว้ (เมื่อฉันคลิกปุ่ม เมธอดจะถูกเรียก) หากฉันกำหนดข้อมูลที่ได้รับให้กับโมเดล UI จะไม่อัปเดต ดังนั้นฉันจึงเพิ่มการเรียกเมธอด $apply เพื่อแจ้ง UI เกี่ยวกับการเปลี่ยนแปลง... ซึ่งทำให้ฉันมีข้อผิดพลาดดังที่กล่าวข้างต้น

อัปเดต:

เอกสารประกอบที่: https://docs.angularjs.org/error/$rootScope/inprog ขอแนะนำให้ใช้ $timeout แทน $apply เพื่อให้แน่ใจว่ามีการดำเนินการแบบอะซิงโครนัส แน่นอนว่านี่เป็นการแก้ไขข้อผิดพลาด แต่ UI ไม่เปลี่ยนแปลง...


person Matze    schedule 30.03.2016    source แหล่งที่มา


คำตอบ (2)


AngularJS สัญญาว่าจะโทร .apply() (ภายใต้ประทุน) แล้วในการโทรกลับ คุณไม่สามารถโทร .apply อีกครั้งภายในการโทรกลับได้เนื่องจากพวกเขากำลังถูก .applied อยู่แล้ว และข้อผิดพลาด "กำลังดำเนินการ" แจ้งสิ่งนั้นอย่างชัดเจน เพียงลบการเรียก .apply ออกและการโทรจะทำงานได้ เว้นแต่คุณจะมีข้อผิดพลาดเพิ่มเติม

person Luis Masuelli    schedule 30.03.2016
comment
ตกลง; ฉันพบว่าเหตุใดฉันจึงไม่เห็นการเปลี่ยนแปลงใด ๆ ใน UI... เป็นเพราะฉันใช้นามแฝง c นอกขอบเขต... ทำให้ฉันโง่ (-; คำตอบของคุณถูกต้อง; ถ้าการเชื่อมโยงดี ก็ไม่มี จำเป็นต้องโทร apply ด้วยตนเอง - person Matze; 30.03.2016

บางทีคุณอาจลอง this.model.data = data; จากนั้น this.scope.apply();

person Alemndra    schedule 30.03.2016