2015-07-20 16 views
22

Mam następujący scenariusz, potrzebuję danych z konkretnego adresu URL. Napisałem funkcję, która przyjmuje parametr "url". Wewnątrz funkcji mam metodę $ http.get, która wywołuje adres URL. Dane mają być zwrócone do funkcji wywołującejsynchroniczne połączenie http w angularJS

var getData = function (url) { 
    var data = ""; 

    $http.get(url) 
     .success(function(response, status, headers, config) { 
      data = response; 
     }) 
     .error(function(errResp) { 
      console.log("error fetching url"); 
     }); 
    return data; 
} 

Problem jest następujący, $ http.get jest asynchroniczna, zanim odpowiedź jest naciągane, funkcja zwraca. Dlatego funkcja wywołująca pobiera dane jako pusty ciąg znaków. Jak zmusić funkcję, aby nie zwracała, dopóki dane nie zostaną pobrane z adresu URL?

+0

Co jest złego w korzystaniu z oddzwonienia lub obietnicy, jak zwykle? – Marty

+1

Możesz sam powrócić do funkcji powodzenia i błędu, które można dalej wykorzystać ... – binariedMe

Odpowiedz

15

Spójrz na obietnic do rozwiązania tych problemów, ponieważ są one używane wszyscy nad miejscem, w kanciastym świecie.

Trzeba użyć $q

var getData = function (url) { 
    var data = ""; 
    var deferred = $q.defer(); 

    $http.get(url) 
     .success(function(response, status, headers, config) { 
      deferred.resolve(response); 
     }) 
     .error(function(errResp) { 
      deferred.reject({ message: "Really bad" }); 
     }); 
    return deferred.promise; 
} 

Oto ciekawy artykuł na promises and $q

UPDATE:

FYI, sama $http usługa zwraca obietnicę, więc $q niekoniecznie jest wymagane w tym scenariuszu (i tym samym anti-pattern).

Ale niech to nie będzie powodem do pominięcia czytania około $ q i obietnic.

więc powyższy kod jest równoważne z następujących:

var getData = function (url) { 
    var data = ""; 
    return $http.get(url); 
} 
+0

Jak uzyskać dostęp do wartości obietnicy? – clearScreen

+0

Dlaczego przegrana? Która część odpowiedzi jest nie do zaakceptowania/zła? – nalinc

+1

To powszechny anty-wzór patrz: https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns –

5

Typowym sposobem na to, co chcesz, jest tak:

var getData = function(url, callback) { 
    $http.get(url).success(function(response) { 
     callback && callback(response); 
    }); 
}; 

używany jak:

getData('/endpoint', function(data) { 
    console.log(data); 
}); 
4

funkcję wydaje się zbędny. Po prostu użyj $http.get(url), ponieważ tak naprawdę nie robisz nic innego, zanim go użyjesz.

var url = 'foo/bar'; 

$http 
    .get(url) 
    .success(function(response, status, headers, config) { 
     $scope.data = response; 
    }) 
    .error(function(errResp) { 
     console.log("error fetching url"); 
    }); 

Jeśli potrzebujesz dostępu do obietnicy, po prostu przypisz ją do zmiennej;

var promise = $http.get(url); 

// some other code.. 

promise.then(function(data){ 
    //.. do something with data 
}); 
8

Można użyć metody q.all $() również rozwiązać ten problem

var requestPromise = []; 

var getData = function (url) { 
    var data = ""; 

    var httpPromise = $http.get(url) 
     .success(function(response, status, headers, config) { 
      data = response; 
     }) 
     .error(function(errResp) { 
      console.log("error fetching url"); 
     }); 

    requestPromise.push(httpPromise); 
} 

w funkcji wywołującej

$q.all(requestPromise).then(function(data) { 

    //this is entered only after http.get is successful 
}); 

upewnij się wstrzykiwać $ q jako zależność. Mam nadzieję, że pomaga