$ apply vs $ digest dalam pengujian direktif

98

Jika saya memiliki arahan yang merespons status atribut tertentu pada cakupan, dan saya ingin mengubah atribut itu dalam pengujian saya dan memverifikasi bahwa itu merespons dengan benar, manakah cara terbaik untuk melakukan perubahan itu?

Saya telah melihat kedua pola ini:

scope.$apply(function() {
    scope.myAttribute = true;
});

dan

scope.myAttribute = true;
scope.$digest();

Apa perbedaan di antara keduanya, dan mana yang lebih baik serta mengapa?

Daniel Roseman
sumber

Jawaban:

206

scope.$digest()akan memecat pengamat pada ruang lingkup saat ini, dan pada semua anaknya juga. scope.$applyakan mengevaluasi fungsi yang lewat dan menjalankan $rootScope.$digest().

Yang pertama lebih cepat, karena perlu mengevaluasi pengamat untuk cakupan saat ini dan anak-anaknya. Yang kedua lebih lambat, karena perlu mengevaluasi pengamat $rootScopedan semua cakupan anak itu.

Ketika kesalahan terjadi di salah satu pengamat dan Anda gunakan scope.$digest, itu tidak ditangani melalui $exceptionHandlerlayanan, jadi Anda perlu menangani sendiri pengecualian. scope.$applymenggunakan try-catchblok secara internal dan meneruskan semua pengecualian ke $exceptionHandler.

Tadeusz Wójcik
sumber
1
Akan $digestjuga disebut pada anak-anak lingkup ini?
pilau
15
Ini bisa menyesatkan. $digesttidak hanya pengamat api pada ruang lingkup saat ini, tetapi juga pada semua anak-anaknya.
tasseKATT
@tasseKATT, saya rasa saya telah menangkap apa yang disarankan oleh komentar Anda.
Hari ini
12

Karena dokumentasinya sendiri menyebutkan $ digest cycle akan dijalankan setiap kali Anda melakukannya $scope.$apply. Sesuai panduan pengembang tentang ruang lingkup

Setelah mengevaluasi ekspresi, metode $ apply melakukan $ digest. Dalam fase $ digest, scope memeriksa semua ekspresi $ watch dan membandingkannya dengan nilai sebelumnya.

Dan sesuai dengan dokumentasi Scope API

Biasanya Anda tidak memanggil $ digest () secara langsung di controller atau direktif. Sebaliknya panggilan ke $ apply () (biasanya dari dalam arahan) akan memaksa $ digest ().

Jadi, Anda tidak boleh memanggil secara eksplisit $digest, $applymetode pemanggilan Anda akan memicu siklus intisari.

Chandermani
sumber
8
ini tidak benar karena intisari sudah cukup untuk sebagian besar kasus di mana hanya cakupan saat ini dan turunannya yang perlu dievaluasi. memang benar bahwa $ scope. $ apply memanggil $ digest secara internal tetapi sangat penting untuk diingat bahwa ini akan berakhir dengan memanggil $ rootScope. $ digest () dan karenanya sangat berat
Srivathsa Harish Venkataramana