Berikut adalah Plunk yang melakukan apa yang Anda inginkan: http://plnkr.co/edit/TTlbSv?p=preview
Idenya adalah Anda bekerja dengan janji secara langsung dan fungsi "lalu" mereka untuk memanipulasi dan mengakses respons yang dikembalikan secara tidak sinkron.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Ini adalah versi yang sedikit lebih rumit yang menyimpan permintaan sehingga Anda hanya membuatnya pertama kali ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ):
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
then
?myService.async()
beberapa kali dari berbagai pengontrol, bagaimana Anda mengatur layanan sehingga hanya melakukan$http.get()
permintaan pertama, dan semua permintaan berikutnya hanya mengembalikan array objek lokal yang akan diatur pada panggilan pertama kemyService.async()
. Dengan kata lain, saya ingin menghindari beberapa permintaan yang tidak perlu ke layanan JSON, padahal sebenarnya saya hanya perlu membuat satu.$scope.data = myService.async()
langsung di controller.Biarkan itu sederhana. Sesederhana itu
promise
dalam layanan Anda (tidak perlu digunakanthen
dalam layanan)then
di controller AndaDemo. http://plnkr.co/edit/cbdG5p?p=preview
sumber
app.factory
, dan dalam kode Anda ituapp.service
. Seharusnyaapp.factory
dalam kasus ini.Karena asinkron,
$scope
ia mendapatkan data sebelum panggilan ajax selesai.Anda dapat menggunakan
$q
dalam layanan Anda untuk membuatpromise
dan mengembalikannya ke pengontrol, dan pengontrol mendapatkan hasilnya saatthen()
dihubungipromise
.Dalam layanan Anda,
Kemudian, di controller Anda:
sumber
this.async = function() {
danthis.getData = function() {return data}
? Saya harap Anda mengerti maksud sayadeffered = $q.defer()
di dalam myService.async jika saya ingin memanggil myService.async () dua atau lebih waktu$q.defer
karena$http
layanan sudah mengembalikan janji. Janji yang dikembalikan akan hang jika$http
mengembalikan kesalahan. Selain itu,.success
dan.error
metode sudah usang dan telah dihapus dari AngularJS 1.6 .tosh shimayama punya solusi tetapi Anda bisa menyederhanakan banyak hal jika menggunakan fakta bahwa $ http mengembalikan janji dan bahwa janji dapat mengembalikan nilai:
Demonstrasi kecil dalam coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Plunker Anda diperbarui dengan metode saya: http://plnkr.co/edit/mwSZGK?p=preview
sumber
Cara yang jauh lebih baik menurut saya akan menjadi seperti ini:
Layanan:
Dan pada controller Anda cukup menggunakan:
Sudut akan secara otomatis menempatkan diselesaikan
awesomeFruits
ke dalam$scope.fruits
.sumber
Saya memiliki masalah yang sama, tetapi ketika saya berselancar di internet saya mengerti bahwa $ http mengembalikan janji secara default, maka saya dapat menggunakannya dengan "lalu" setelah mengembalikan "data". lihat kode:
sumber
Saat mengikat UI ke array Anda, Anda ingin memastikan Anda memperbarui array yang sama secara langsung dengan mengatur panjang ke 0 dan mendorong data ke dalam array.
Alih-alih ini (yang menetapkan referensi array berbeda
data
yang tidak akan diketahui oleh UI Anda):coba ini:
Berikut adalah biola yang menunjukkan perbedaan antara pengaturan array baru vs pengosongan dan menambahkan ke yang sudah ada. Saya tidak bisa membuat plnkr Anda berfungsi, tapi semoga ini berhasil untuk Anda!
sumber
angular.copy(d, data)
juga akan bekerja. Ketika suatu tujuan disuplai ke metode salin (), itu pertama-tama akan menghapus elemen-elemen tujuan, dan kemudian menyalin yang baru dari sumber.Terkait dengan ini saya mengalami masalah yang sama, tetapi tidak dengan get atau post yang dibuat oleh Angular tetapi dengan ekstensi yang dibuat oleh pihak ke-3 (dalam kasus saya, Chrome Extension).
Masalah yang saya hadapi adalah bahwa Ekstensi Chrome tidak akan kembali
then()
sehingga saya tidak dapat melakukannya dengan cara di solusi di atas tetapi hasilnya masih Asynchronous.Jadi solusi saya adalah membuat layanan dan melanjutkan panggilan balik
Kemudian di controller saya
Semoga ini bisa membantu orang lain mendapatkan masalah yang sama.
sumber
Saya telah membaca http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS memungkinkan kami untuk merampingkan logika pengontrol kami dengan menempatkan janji langsung pada ruang lingkup, daripada menyerahkan secara manual secara terselesaikan nilai dalam panggilan balik sukses.]
sangat sederhana dan praktis :)
Semoga bantuan ini
sumber
defrred.promise
bukan fungsi.$scope.items = Data.getData();
ini tidak digunakan lagi dalam AnglularSaya benar-benar tidak menyukai kenyataan bahwa, karena cara "janji" dalam melakukan sesuatu, konsumen layanan yang menggunakan $ http harus "tahu" tentang cara membongkar tanggapan.
Saya hanya ingin memanggil sesuatu dan mengeluarkan data, mirip dengan
$scope.items = Data.getData();
cara lama , yang sekarang sudah usang .Saya mencoba untuk sementara waktu dan tidak menghasilkan solusi yang sempurna, tapi inilah foto terbaik saya ( Plunker ). Mungkin bermanfaat bagi seseorang.
Kemudian controller:
Kekurangan yang sudah bisa saya temukan
getData
hanya dapat menerimaobj
parameter dalam bentuk objek (walaupun itu juga bisa menerima array), yang tidak akan menjadi masalah bagi banyak aplikasi, tetapi ini adalah batasan yang sangat$scope.data
dengan= {}
menjadikannya objek (pada dasarnya apa yang$scope.clearData()
dilakukan di atas), atau= []
untuk array, atau tidak akan berfungsi (kami sudah harus mengasumsikan sesuatu tentang data apa yang akan datang). Saya mencoba melakukan langkah persiapan inigetData
, tetapi tidak berhasil.Namun demikian, ia menyediakan pola yang menghilangkan pelat boiler "janji dibuka", dan mungkin berguna dalam kasus ketika Anda ingin menggunakan data tertentu yang diperoleh dari $ http di lebih dari satu tempat sambil menjaganya tetap KERING.
sumber
Sejauh menyangkut caching respons dalam layanan, berikut adalah versi lain yang tampaknya lebih jelas daripada yang saya lihat sejauh ini:
layanan ini akan mengembalikan data yang di-cache atau
$http.get
;sumber
Silakan coba Kode di bawah ini
sumber