2013-08-24 18 views
81

Birden çok sayfada RESTful hizmetinden gelen bazı verileri kullanıyorum. Bunun için açısal fabrikaları kullanıyorum. Bu yüzden, verileri sunucudan bir kez almam gerekiyordu ve her defasında bu tanımlı hizmetle veri alıyorum. Aynı küresel değişkenler gibi. Benim gereksinimleri başı olarak benim için iyi çalışan

function myFunction($scope, myService) { 
    $scope.data = myService; 
    console.log("data.name"+$scope.data.name); 
} 

Its: Ben bu hizmeti kullanıyorum benim denetleyicisi olarak

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

myApp.factory('myService', function($http) { 
    $http({method:"GET", url:"/my/url"}).success(function(result){ 
     return result; 
    }); 
}); 

: İşte örnektir. Fakat sorun şu ki, web sayfamda yeniden yüklendiğimde servis tekrar çağrılacak ve sunucu isteğinde bulunacak. "Tanımlı Hizmet" e bağlı başka bir fonksiyonun arasında yürütülürse, "bir şey" tanımlanmamış gibi bir hata verir. Bu yüzden, hizmet yüklenene kadar komut dizimde beklemek istiyorum. Bunu nasıl yapabilirim? Angularjs'de böyle bir şey var mı?

cevap

138

Ne zaman tamamlanacağını bilmediğiniz durumlarda asenkron işlemleri sözlerini kullanmalısınız. Bir söz "henüz tamamlanmamış, ancak gelecekte beklenen bir operasyonu temsil eder." Düzenleme

myApp.factory('myService', function($http) { 

    var getData = function() { 

     // Angular $http() and then() both return promises themselves 
     return $http({method:"GET", url:"/my/url"}).then(function(result){ 

      // What we return here is the data that will be accessible 
      // to us after the promise resolves 
      return result.data; 
     }); 
    }; 


    return { getData: getData }; 
}); 


function myFunction($scope, myService) { 
    var myDataPromise = myService.getData(); 
    myDataPromise.then(function(result) { 

     // this is only run after getData() resolves 
     $scope.data = result; 
     console.log("data.name"+$scope.data.name); 
    }); 
} 

: Sujoys İlişkin ne yapıyoruz O myFuction() çağrısı .sonra kadar döndürmez Bunun gerekli olduğunu yorumlamak) (gibi (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)

Bir örnek uygulama olacaktır işlev yürütmeyi tamamlar.

function myFunction($scope, myService) { 
    var myDataPromise = myService.getData(); 
    myDataPromise.then(function(result) { 
     $scope.data = result; 
     console.log("data.name"+$scope.data.name); 
    }); 
    console.log("This will get printed before data.name inside then. And I don't want that."); 
} 

Peki, getData çağrısı() varsayalım tamamlanması 10 saniye sürdü. Eğer işlev o zaman hiçbir şey döndürmezse, normal senkron kod haline gelir ve tarayıcı tamamlanıncaya kadar beklerdi.

Anında geri dönen sözle, tarayıcı bu arada diğer kodlarla devam etmekte serbesttir. Sözler çözüldüğünde/başarısız olduğunda, o zaman() çağrısı tetiklenir. Bu nedenle, kodunuzun akışını biraz daha karmaşık hale getirse bile (karmaşıklık genel olarak asenkron/paralel programlamanın sık rastlanan bir sorundur!)

+2

Bu, sorunumu çözdü! Herkes için, ajax çağrısından veri gerektiren bir açılır kapanışım vardı, bu yüzden kapsam oluşturulduğunda veriler mevcut değildi. Bu erteleme ile, ajax çağrısından gelen verilere sahip olmak için kapsam atanabilir. –

+6

@mikel: Burada başka bir sorum var. MyFuction() çağrınız hemen dönecek ancak bu söz .then() daha sonra arayacak. Ne yapmam gerekiyor? MyFuction() çağrısı .then() işlevi yürütmeyi bitirene kadar geri dönmeyecek. 'function myFunction ($ kapsamı, myService) { var myDataPromise = myService.getData(); myDataPromise.then (işlev (sonuç) { $ scope.data = sonuç; console.log ("data.name" + $ scope.data.name); }); console.log ("Bu, içindeki data.name'den önce yazdırılacaktır. Ve bunu istemiyorum."); } ' – Sujoy

12

Bu konuda yeni kişiler için

DataHandler.GetRandomArtists(3, function(response){ 
     $scope.data.random_artists = response; 
    }); 
+0

Harika çözüm. Ona bakarken aynı çizgide düşünmekteydim. Birisi bunu buraya koyduğuna sevindim. – Nate

0

Bunları eğer aynı sorunu ve hiçbiri olmamdı: kumandanızda olarak

.factory('DataHandler',function ($http){ 

    var GetRandomArtists = function(data, callback){ 
    $http.post(URL, data).success(function (response) { 
     callback(response); 
     }); 
    } 
}) 

: En hizmetinde

: Ayrıca örneğin bir geri arama kullanabilirsiniz benim için çalıştı. İşte

app.factory('myService', function($http) { 
    var data = function (value) { 
      return $http.get(value); 
    } 

    return { data: data } 
}); 

ve öyle kullanır işlev

...

vm.search = function(value) { 

     var recieved_data = myService.data(value); 

     recieved_data.then(
      function(fulfillment){ 
       vm.tags = fulfillment.data; 
      }, function(){ 
       console.log("Server did not send tag data."); 
     }); 
    }; 

hizmet o gerekli değildir ama genişletilebilirlik için iyi bir uygulama düşünüyorum ... gerçi işe yaramadı ne . İhtiyacınız olan şeylerin çoğu, özellikle API'leri kullanırken, başkaları için olacak. Neyse, umarım bu yardımcı oldu.

0

FYI, bu Angularfire kullanıyor, bu yüzden farklı bir hizmet veya başka bir kullanım için biraz değişiklik gösterebilir, ancak aynı $ http un'u çözmesi gerekir. Aynı sorunu benim için en uygun olan tek çözüm, tüm hizmetleri/fabrikaları kapsamdaki tek bir sözle birleştirmekti. bu hizmetleri gerekli her rota/görünümünde/vs ben

myservice.$loaded().then(function() {$rootScope.myservice = myservice;}); 

ve koyun auth sonra kaçak denetleyici fonksiyonu yani myfunct (iç veri yüklenen gerektiren herhangi bir işlev) ve ana app.js koymak yüklenecek böylece kontrolör zaman uyumsuz sözler/sipariş/que endişelenmeden

myfunct() 

içindeki her şeyi çalıştırabilir görünümünde sadece ilk/ana görünüm element/ambalajında ​​

ng-if="myservice" ng-init="somevar=myfunct()" 

vermedi Sorunlar Umarım aynı sorunları olan birine yardım eder.

İlgili konular