gunakan $ http di dalam penyedia khusus di konfigurasi aplikasi, angular.js

90

Pertanyaan utama - apakah mungkin? Saya mencoba tetapi tidak berhasil ..

app.js utama

...
var app = angular.module('myApp', ['services']);
app.config(['customProvider', function (customProvider) {

}]);
...

penyedia itu sendiri

var services = angular.module('services', []);
services.provider('custom', function ($http) {
});

Dan saya mendapat kesalahan seperti itu:

Uncaught Error: Unknown provider: $http from services 

Ada ide?

Terima kasih!

Kosmetika
sumber
kawan, ya itu benar, tapi saya sedang berbicara tentang app.configbagian
Kosmetika
saya juga tahu tentang batasan ini tetapi berpikir bahwa di dalam provider itu mungkin entah bagaimana ..
Kosmetika

Jawaban:

158

Intinya adalah:

  • Anda TIDAK DAPAT menyuntikkan layanan ke bagian konfigurasi penyedia .
  • Anda BISA memasukkan layanan ke bagian yang menginisialisasi layanan penyedia .

Rincian:

Kerangka sudut memiliki proses inisialisasi 2 fase:

TAHAP 1: Konfigurasi

Selama configfase ini semua penyedia diinisialisasi dan semua configbagian dijalankan. The configbagian mungkin berisi kode yang mengkonfigurasi benda penyedia dan karena itu mereka dapat disuntik dengan benda penyedia. Namun, karena penyedia adalah pabrik untuk objek layanan dan pada tahap ini penyedia tidak sepenuhnya diinisialisasi / dikonfigurasi -> Anda tidak dapat meminta penyedia untuk membuat layanan untuk Anda pada tahap ini -> pada tahap konfigurasi Anda tidak dapat menggunakan / layanan suntik . Saat fase ini selesai, semua penyedia sudah siap (tidak ada lagi konfigurasi penyedia yang dapat dilakukan setelah fase konfigurasi selesai).

TAHAP 2: Jalankan

Selama runfase semua runbagian dieksekusi. Pada tahap ini penyedia sudah siap dan dapat membuat layanan -> selama runtahap Anda dapat menggunakan / menyuntikkan layanan .

Contoh:

1. Menyuntikkan $httplayanan ke fungsi inisialisasi penyedia TIDAK AKAN berfungsi

//ERRONEOUS
angular.module('myModule').provider('myProvider', function($http) {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function() {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Karena kami mencoba menyuntikkan $httplayanan ke dalam fungsi yang dijalankan selama configfase, kami akan mendapatkan kesalahan:

Uncaught Error: Unknown provider: $http from services 

Apa yang sebenarnya dikatakan kesalahan ini adalah bahwa $httpProvideryang digunakan untuk membuat $httplayanan belum siap (karena kita masih dalam configfase).

2. Menyuntikkan $httplayanan ke fungsi inisialisasi layanan AKAN berfungsi:

//OK
angular.module('myModule').provider('myProvider', function() {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function($http) {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Karena kita sekarang memasukkan layanan ke dalam fungsi inisialisasi layanan, yang dijalankan selama runfase, kode ini akan berfungsi.

Dana Shalev
sumber
63
Jawaban yang bagus, tetapi meskipun menjelaskan bagaimana tidak mungkin memasukkan layanan selama konfigurasi, itu tidak menjelaskan cara membuat HTTP POST / GET selama konfigurasi. Ini penting untuk aplikasi yang dikonfigurasi menggunakan nilai yang disediakan oleh API.
Sean O'Dell
3
@ Braw & Kosmetika - Satu-satunya hal yang menurut saya perlu Anda minta selama fase konfigurasi adalah beberapa jenis objek pengaturan. Mungkin itu berisi API endpoint, informasi pengguna, lokal pengguna dan pengaturan bahasa, dll. Jika demikian, saya akan merekomendasikan untuk memasukkan informasi tersebut ke dalam sumber javascript. Anda dapat menggunakan rendering sisi server di index.html untuk memasukkan beberapa setelan sehingga tersedia sebelum aplikasi Anda diinisialisasi. Segala sesuatu yang lain, saya akan mencoba mencari cara untuk melakukannya setelah init
Sean Clark Hess
2
@ Sean: Cara membuat HTTP POST / GET adalah pertanyaan yang berbeda dari pertanyaan OP (Apakah mungkin menggunakan $ http di dalam fase konfigurasi?), Dan mungkin layak mendapat postingan terpisah sama sekali; Karena sifat sinkron dari fase konfigurasi Angular, cara yang baik untuk menyediakan data sisi server ke kode konfigurasi Anda adalah dengan merendernya sebagai objek javascript di laman HTML Anda selama perenderan sisi server (mis <script>var config = <% = mySettings.toJson() %>;</script>.). Ini dapat dilakukan dengan menggunakan mesin templating seperti Smarty untuk PHP, Jinja2 untuk Python, Nunchucks untuk NodeJS, dll.
Trevor
4
@threed: Memasukkan data konfigurasi langsung ke HTML atau js di server hanya berfungsi jika kode klien Anda berasal dari server yang sama. Dengan CORS, sekarang mungkin (dan sangat diinginkan) untuk memiliki kode klien yang disajikan dari server yang berbeda, dan data disajikan dari server terpisah. Dalam kasus tersebut, kita perlu mengambil data konfigurasi menggunakan HTTP.
Bernard
4
Meskipun ini adalah sebuah jawaban, itu bukanlah jawaban atas pertanyaan yang ditanyakan.
Eric
64

Ini mungkin memberi Anda sedikit pengaruh:

var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');

Tapi hati-hati, callback berhasil / error mungkin membuat Anda berada dalam kondisi balapan antara aplikasi dimulai dan respons server.

Cody
sumber
6
"Jawaban yang diterima" gagal untuk penyedia saya ... Saya menghabiskan 2 hari frustrasi mencoba membuatnya berhasil tanpa harapan. Pendekatan Anda langsung berhasil.
Dave Alperovich
Dapatkah Anda menjelaskan apakah instance yang dibuat di sini adalah layanan tunggal "nyata" atau hanya instance dari layanan yang dibuang saat Angular melakukan sihir injektor yang sebenarnya.
Eric
Eric, saya tidak bisa memastikannya saat ini. Namun, yang biasanya saya lakukan (jika memungkinkan) adalah angular.injector(['mymodule'])- tetapi saya tidak yakin apakah Anda dapat menggunakan pendekatan ini untuk $httplayanan tersebut. Saya ingin mengatakan saya punya. Tidak yakin apakah ini membantu atau tidak: - /
Cody
2
Ini harus menjadi jawaban yang diterima. Saya berjuang untuk selamanya ketika mencoba untuk membuat ini bekerja, dan pendekatan ini menyelesaikan masalah saya dengan segera. Saya pikir ini mungkin masalah yang sangat umum. Terima kasih @Cody
iamdash
5
Saya mengonfirmasi bahwa solusi yang diterima tidak berfungsi untuk menggunakan $ http di penyedia. Tapi jawaban @Cody berhasil
Dino
1

Ini adalah pertanyaan lama, sepertinya kita memiliki beberapa masalah telur ayam yang terjadi jika kita ingin mengandalkan kapabilitas inti dari perpustakaan.

Alih-alih memecahkan masalah dengan cara yang mendasar, yang saya lakukan adalah jalan pintas. Buat arahan yang membungkus seluruh tubuh. Ex.

<body ng-app="app">
  <div mc-body>
    Hello World
  </div>
</body>

Sekarang mc-bodyperlu diinisialisasi sebelum rendering (sekali), mis.

link: function(scope, element, attrs) {
  Auth.login().then() ...
}

Auth adalah layanan atau penyedia, mis.

.provider('Auth', function() {
  ... keep your auth configurations
  return {
    $get: function($http) {
      return {
        login: function() {
          ... do something about the http
        }
      }
    }
  }
})

Tampak bagi saya bahwa saya memiliki kendali atas urutan bootstrap, itu setelah bootstrap biasa menyelesaikan semua konfigurasi penyedia dan kemudian mencoba untuk menginisialisasi mc-bodydirektif.

Dan arahan ini menurut saya bisa di depan routing, karena routing juga disuntikkan melalui ex direktif. <ui-route />. Tapi saya bisa salah dalam hal ini. Perlu investigasi lebih lanjut.

windmaomao.dll
sumber
Bisakah Anda menjelaskan solusi Anda?
Tandai
-2

Menanggapi pertanyaan Anda, "Ada Ide?", Saya akan menjawab dengan "ya". Tapi tunggu, masih ada lagi!

Saya sarankan hanya menggunakan JQuery di konfigurasi. Sebagai contoh:

var app = angular.module('myApp', ['services']);
app.config(['$anyProvider', function ($anyProvider) {
    $.ajax({
        url: 'www.something.com/api/lolol',
        success: function (result) {
            $anyProvider.doSomething(result);
        }
    });
}]);
Suamere
sumber
$ customProvider dalam callback sukses menyertakan $ seolah-olah ini adalah penyedia internal.
Jeff Fischer
1
Anda benar bahwa saya memiliki campuran $ dan bukan- $. Saya memperbaruinya menjadi $.
Suamere