Bagaimana saya bisa menguji layanan AngularJS dari konsol?

395

Saya memiliki layanan seperti:

angular.module('app').factory('ExampleService', function(){
  this.f1 = function(world){
    return 'Hello '+world;
  }
  return this;
})

Saya ingin mengujinya dari konsol JavaScript dan memanggil fungsi f1()layanan.

Bagaimana saya bisa melakukan itu?

JustGoscha
sumber

Jawaban:

713

TLDR: Dalam satu baris perintah yang Anda cari:

angular.element(document.body).injector().get('serviceName')

Menyelam dalam

AngularJS menggunakan Dependency Injection (DI) untuk menyuntikkan layanan / pabrik ke dalam komponen, arahan dan layanan lainnya. Jadi yang perlu Anda lakukan untuk mendapatkan layanan adalah untuk mendapatkan injektor AngularJS terlebih dahulu (injektor bertanggung jawab untuk memasang semua dependensi dan menyediakannya untuk komponen).

Untuk mendapatkan injektor aplikasi Anda, Anda perlu mengambilnya dari elemen yang ditangani sudut. Misalnya jika aplikasi Anda terdaftar pada elemen tubuh yang Anda panggilinjector = angular.element(document.body).injector()

Dari diambil injectorAnda kemudian bisa mendapatkan layanan apa pun yang Anda sukainjector.get('ServiceName')

Informasi lebih lanjut tentang itu dalam jawaban ini: Tidak dapat mengambil injektor dari sudut
Dan bahkan lebih lanjut di sini: Panggil AngularJS dari kode lama


Trik lain yang berguna untuk mendapatkan $scopeelemen tertentu. Pilih elemen dengan alat inspeksi DOM alat pengembang Anda dan kemudian jalankan baris berikut ( $0selalu elemen yang dipilih):
angular.element($0).scope()

JustGoscha
sumber
70
Saya juga harus melakukan ini untuk membuatnya bekerja. BTW, angular.element('*[ng-app]').injector()harus bekerja untuk semua kasus.
Francesc Rosas
4
Jika Anda mendapatkan kesalahan 'penyeleksi tidak diterapkan' mengeksekusi angular.element ('html') maka Anda dapat menggunakan fitur Chrome $ 0. Pilih elemen html, pergi ke konsol dan jalankan angular.element ($ 0) .injector ()
Marek
9
documentjuga berfungsi:angular.element(document).injector().get('serviceName')
Tamlyn
1
FYI Saya harus menggunakan document.body on chrome
Kevin
5
FYI Saya ingin menggunakan layanan $ location, tetapi akhirnya saya harus membungkusnya dengan scope.apply. Saya tahu ini didokumentasikan dengan baik, tetapi itu telah menyelinap di pikiran saya. Dalam satu baris, angular.element (document) .scope (). $ Berlaku (angular.element (document) .injector (). Get ('$ location'). Path ('/ my / angular / url'))
acid_crucifix
25

Pertama-tama, versi modifikasi dari layanan Anda.

Sebuah )

var app = angular.module('app',[]);

app.factory('ExampleService',function(){
    return {
        f1 : function(world){
            return 'Hello' + world;
        }
    };
});

Ini mengembalikan objek, tidak ada yang baru di sini.

Sekarang cara untuk mendapatkan ini dari konsol adalah

b)

var $inj = angular.injector(['app']);
var serv = $inj.get('ExampleService');
serv.f1("World");

c)

Salah satu hal yang Anda lakukan di sana sebelumnya adalah mengasumsikan bahwa app.factory mengembalikan Anda fungsi itu sendiri atau versi yang baru. Yang tidak demikian. Untuk mendapatkan konstruktor, Anda harus melakukannya

app.factory('ExampleService',function(){
        return function(){
            this.f1 = function(world){
                return 'Hello' + world;
            }
        };
    });

Ini mengembalikan konstruktor ExampleService yang selanjutnya Anda harus melakukan 'baru'.

Atau sebagai alternatif,

app.service('ExampleService',function(){
            this.f1 = function(world){
                return 'Hello' + world;
            };
    });

Ini mengembalikan ExampleService () baru pada injeksi.

Ganaraj
sumber
3
ketika saya lakukan var $inj = angular.injector(['app']);maka konsol melempar Error: Unknown provider: $filterProvider from appdalam satu aplikasi dan Error: Unknown provider: $controllerProvider from appdi aplikasi lain ...
JustGoscha
@JustGoscha Bagaimana aplikasi Anda dikonfigurasi? yaitu Bagaimana garis (yang terlihat seperti) var app = angular.module ('app', []); terlihat seperti di aplikasi Anda.
ganaraj
Saya tidak sepenuhnya memahami pertanyaan .. sepertinya seperti yang Anda katakan angular.module('app',[]);dan kemudian ada layanan, controller dll dalam file yang berbeda dan mereka semua didefinisikan seperti angular.module('app').factory('FeatureRegistry',function(){//code here});misalnya
JustGoscha
@JustGoscha Inilah yang saya lakukan untuk menguji. Saya pergi ke docs.angularjs.org/api di chrome. Membuka konsol. Mengetik kode di bagian a dari jawaban saya dan kemudian mengetik kode di bagian b .. Anda harus melihat Hello World .. Bisakah Anda mencobanya?
ganaraj
14

@ Jawaban JustGoscha tepat, tapi itu banyak yang harus diketik ketika saya ingin akses, jadi saya menambahkan ini ke bagian bawah app.js. Maka yang harus saya ketik adalah x = getSrv('$http')untuk mendapatkan layanan http.

// @if DEBUG
function getSrv(name, element) {
    element = element || '*[ng-app]';
    return angular.element(element).injector().get(name);
}
// @endif

Ini menambahkannya ke lingkup global tetapi hanya dalam mode debug. Saya memasukkannya ke dalam @if DEBUGsehingga saya tidak berakhir dengan itu dalam kode produksi. Saya menggunakan metode ini untuk menghapus kode debug dari build prouduction.

pembuat perahu
sumber
4

Kerangka kerja Dependency Angularjs bertanggung jawab untuk menyuntikkan ketergantungan modul aplikasi Anda ke pengontrol Anda. Ini dimungkinkan melalui injektornya.

Anda harus terlebih dahulu mengidentifikasi aplikasi-ng dan mendapatkan injektor terkait. Kueri di bawah ini berfungsi untuk menemukan aplikasi-ng Anda di DOM dan mengambil injektor.

angular.element('*[ng-app]').injector()

Namun, di chrome, Anda dapat mengarahkan ke target ng-aplikasi seperti yang ditunjukkan di bawah ini. dan gunakan $0retasan dan masalahangular.element($0).injector()

Setelah Anda memiliki injector, dapatkan layanan injeksi dependensi seperti di bawah ini

injector = angular.element($0).injector();
injector.get('$mdToast');

masukkan deskripsi gambar di sini

Faiz Mohamed Haneef
sumber