Angularjs cinsinden $ http talebinden yanıt gelene kadar nasıl beklenir?


94

Bir RESTful hizmetinden gelen bazı verileri birden çok sayfada kullanıyorum. Bu yüzden bunun için köşeli fabrikalar kullanıyorum. Bu nedenle, verileri sunucudan bir kez almak zorunda kaldım ve her seferinde verileri bu tanımlı hizmetle alıyorum. Tıpkı küresel değişkenler gibi. İşte örnek:

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

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

Denetleyicimde bu hizmeti şu şekilde kullanıyorum:

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

Gereksinimlerime göre benim için iyi çalışıyor. Ancak buradaki sorun şu ki, web sayfamı yeniden yüklediğimde servis tekrar aranıyor ve sunucu için talepte bulunacak. Aralarında "tanımlı hizmete" bağlı olan başka bir işlev çalıştırılırsa, "bir şey" tanımsız gibi bir hata verir. Bu yüzden servis yüklenene kadar komut dosyamda beklemek istiyorum. Bunu nasıl yapabilirim? Bunu angularjs'de zaten var mı?

Yanıtlar:


151

Ne zaman tamamlanacağını bilmediğiniz zaman uyumsuz işlemler için sözler kullanmalısınız. Bir söz, "henüz tamamlanmamış ancak gelecekte beklenen bir işlemi temsil eder." ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise )

Örnek bir uygulama şöyle olacaktır:

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);
    });
}

Düzenleme: Sujoys yorumuyla ilgili olarak , myFuction () çağrısının .then () işlevi yürütmeyi bitirene kadar geri dönmemesi için ne yapmam gerektiğini söyler.

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ının tamamlanmasının 10 saniye sürdüğünü varsayalım. İşlev bu süre içinde hiçbir şey döndürmezse, etkin bir şekilde normal eşzamanlı kod haline gelir ve tamamlanana kadar tarayıcıyı kilitler.

Sözün anında geri dönmesiyle birlikte, tarayıcı bu arada diğer kodlarla devam etmekte özgürdür. Söz çözüldüğünde / başarısız olduğunda, then () çağrısı tetiklenir. Bu nedenle, kodunuzun akışını biraz daha karmaşık hale getirse bile bu şekilde çok daha mantıklıdır (karmaşıklık genel olarak eşzamansız / paralel programlamanın ortak bir sorunudur!)


2
Bu benim sorunumu çözdü !!! Başkaları için, ajax çağrısından veri gerektiren bir açılır listeye sahiptim, bu nedenle kapsam oluşturulduğunda veriler mevcut değildi. Bu erteleme ile, kapsam, ajax çağrısından gelen verilere sahip olacak şekilde atanabilir.
Kat Lim Ruiz

8
@mikel: Burada başka bir sorum var. MyFuction () aramanız hemen geri dönecek, ancak bu söz. Sonra () daha sonra arayacaktır. MyFuction () çağrısının .then () işlevi yürütmeyi bitirene kadar dönmemesi için ne yapmam gerekiyor? 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."); }
Sujoy

13

buna yeni başlayanlar için, örneğin bir geri aramayı da kullanabilirsiniz:

Hizmetinizde:

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

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

Denetleyicinizde:

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

Harika çözüm. Ben bakarken aynı çizgide düşünüyordum. Birinin bunu oraya koymasına sevindim.
Nate

0

Bilginize, bu Angularfire kullanıyor, bu nedenle farklı bir hizmet veya başka bir kullanım için biraz değişiklik gösterebilir, ancak $ http'nin sahip olduğu sorunu çözmelidir. Aynı sorunu yaşadım, bana en uygun çözüm, tüm hizmetleri / fabrikaları kapsamda tek bir sözde birleştirmekti. Bu hizmetlerin / etc'nin yüklenmesini gerektiren her yol / görünümde, denetleyici işlevinin içine yüklenmiş veri gerektiren tüm işlevleri, yani myfunct () ve yetkilendirmeden sonra çalıştırılan ana app.js'yi koydum.

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

ve az önce yaptığım görünümde

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

ilk / üst görünüm öğesinde / sarmalayıcıda, denetleyici içindeki her şeyi çalıştırabilir

myfunct()

zaman uyumsuz vaatler / sipariş / kuyruk sorunları hakkında endişelenmeden. Umarım bu, sahip olduğum sorunları yaşayan birine yardımcı olur.


0

Aynı sorunu yaşıyordum ve bunlar benim için işe yaramadıysa hiçbiri. İşte yine de işe yarayan şey ...

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

    return { data: data }
});

ve sonra onu kullanan 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 kadar gerekli değil, ancak bunun genişletilebilirlik için iyi bir uygulama olduğunu düşünüyorum. Biri için ihtiyaç duyacağınız şeylerin çoğu, özellikle API'leri kullanırken diğerleri için olacaktır. Neyse umarım bu yardımcı olmuştur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.