Apa praktik terbaik untuk melakukan panggilan AJAX di Angular.js?

151

Saya sedang membaca artikel ini: http://eviltrout.com/2013/06/15/ember-vs-angular.html

Dan katanya,

Karena kurangnya konvensi, saya bertanya-tanya berapa banyak proyek Angular bergantung pada praktik buruk seperti panggilan AJAX langsung di dalam pengontrol? Karena injeksi ketergantungan, apakah pengembang menyuntikkan parameter router ke arahan? Apakah pengembang AngularJS pemula akan menyusun kode mereka dengan cara yang oleh pengembang AngularJS berpengalaman dianggap idiomatik?

Saya sebenarnya $httpmenelepon dari pengontrol Angular.js saya. Mengapa itu praktik yang buruk? Apa praktik terbaik untuk melakukan $httppanggilan itu? dan mengapa?

Stroberi
sumber
12
+1 untuk merujuk pada postingan menarik yang membandingkan bara dan angular.
Chandermani
Saya juga bertanya-tanya tentang Praktik Terbaik Sudut
Dalorzo
Juga pelengkap juga memeriksa API untuk hal-hal yang mungkin Anda lewatkan: docs.angularjs.org/api/ng/service/$http
Christophe

Jawaban:

174

EDIT: Jawaban ini terutama berfokus pada versi 1.0.X. Untuk mencegah kebingungan, ini sedang diubah untuk mencerminkan jawaban terbaik untuk SEMUA versi Angular saat ini pada hari ini, 2013-12-05.

Idenya adalah untuk membuat layanan yang mengembalikan janji ke data yang dikembalikan, kemudian memanggilnya di controller Anda dan menangani janji di sana untuk mengisi properti $ scope Anda.

Layanan

module.factory('myService', function($http) {
   return {
        getFoos: function() {
             //return the promise directly.
             return $http.get('/foos')
                       .then(function(result) {
                            //resolve the promise as the data
                            return result.data;
                        });
        }
   }
});

Pengendali:

Tangani metode janji then()dan dapatkan data darinya. Setel properti $ scope, dan lakukan apa pun yang mungkin perlu Anda lakukan.

module.controller('MyCtrl', function($scope, myService) {
    myService.getFoos().then(function(foos) {
        $scope.foos = foos;
    });
});

Resolusi Janji Dalam-Pandangan (hanya 1.0.X):

Dalam Angular 1.0.X, target dari jawaban asli di sini, janji-janji akan mendapat perlakuan khusus oleh View. Ketika mereka menyelesaikan, nilai yang diselesaikan akan terikat pada tampilan. Ini telah ditinggalkan dalam 1.2.X

module.controller('MyCtrl', function($scope, myService) {
    // now you can just call it and stick it in a $scope property.
    // it will update the view when it resolves.
    $scope.foos = myService.getFoos();
});
Ben Lesh
sumber
4
Sebagai tambahan, ini hanya berfungsi ketika Anda menggunakan $scope.foosproperti dalam templat. Jika Anda menggunakan properti yang sama di luar templat (misalnya dalam fungsi lain), objek yang disimpan masih ada objek janji.
Clark Pan
1
Saat ini saya menggunakan pola ini di aplikasi sudut baru, namun saya bertanya-tanya di halaman mentah bagaimana cara mendapatkan akses ke properti yang saya terikat ke lingkup, dalam contoh ini jika saya ingin mengambil data dari getFoos dan memposting perubahan ke Itu. jika saya mencoba dan mengakses $ scope.foos dalam pembaruan saya, saya punya objek janji dan bukan data, saya bisa melihat bagaimana cara mendapatkan data dalam objek itu sendiri, tetapi tampaknya benar-benar sangat hacky.ideas?
Kelly Milligan
5
@KellyMilligan, dalam pola ini, itu adalah mengikat yang tahu apa yang harus dilakukan dengan janji. Jika Anda perlu mengakses objek dari tempat lain, Anda harus menangani .then()janji itu dan memasukkan nilainya dalam $ scope ...myService.getFoos().then(function(value) { $scope.foos = value; });
Ben Lesh
1
Hanya pembaruan pada teknik ini, pada 1.2.0-rc.3, pembatalan janji secara otomatis telah ditinggalkan, sehingga teknik ini tidak lagi berfungsi.
Clark Pan
2
Punya beberapa downvotes di sini baru-baru ini, mungkin karena itu tidak lagi sejalan dengan versi terbaru dari Angular. Saya telah memperbarui jawaban untuk mencerminkan hal itu.
Ben Lesh
45

Praktik terbaik adalah dengan abstrak $httppanggilan keluar menjadi 'layanan' yang menyediakan data ke controller Anda:

module.factory('WidgetData', function($http){
    return {
        get : function(params){
            return $http.get('url/to/widget/data', {
                params : params
            });
        }
    }
});

module.controller('WidgetController', function(WidgetData){
    WidgetData.get({
        id : '0'
    }).then(function(response){
        //Do what you will with the data.
    })
});

Abstraksi $httppanggilan seperti ini akan memungkinkan Anda untuk menggunakan kembali kode ini di beberapa pengontrol. Ini menjadi penting ketika kode yang berinteraksi dengan data ini menjadi lebih kompleks, mungkin Anda ingin memproses data sebelum menggunakannya di controller Anda, dan menyimpan hasil cache dari proses itu sehingga Anda tidak perlu menghabiskan waktu untuk memprosesnya kembali.

Anda harus menganggap 'layanan' sebagai representasi (atau Model) data yang dapat digunakan aplikasi Anda.

Clark Pan
sumber
9

Jawaban yang diterima memberi saya $http is not definedkesalahan jadi saya harus melakukan ini:

var policyService = angular.module("PolicyService", []);
policyService.service('PolicyService', ['$http', function ($http) {
    return {
        foo: "bar",
        bar: function (params) {
            return $http.get('../Home/Policy_Read', {
                params: params
            });
        }
    };
}]);

Perbedaan utama adalah baris ini:

policyService.service('PolicyService', ['$http', function ($http) {
pengguna1477388
sumber
1

Saya memberikan jawaban untuk seseorang yang menginginkan layanan web yang sepenuhnya generik di Angular. Saya sarankan hanya menghubungkannya dan itu akan menangani semua panggilan layanan web Anda tanpa perlu kode semuanya sendiri. Jawabannya ada di sini:

https://stackoverflow.com/a/38958644/5349719

pemusnah
sumber