web-dev-qa-db-fra.com

Appel http synchrone dans angularJS

J'ai le scénario suivant, j'ai besoin des données d'une URL particulière. J'ai écrit une fonction qui prend le paramètre 'url'. Dans la fonction, j'ai la méthode $ http.get qui appelle la URL. Les données doivent être renvoyées à la fonction appelante

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

Le problème est le suivant: $ http.get est asynchrone. Avant que la réponse ne soit extraite, la fonction retourne. Par conséquent, la fonction appelante obtient les données sous forme de chaîne vide. Comment forcer la fonction à ne pas renvoyer avant que les données aient été extraites de l'URL?

28
clearScreen

Jetez un coup d'oeil aux promesses de surmonter ces problèmes, car elles sont utilisées partout, dans le monde angular.

Vous devez utiliser $ 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;
}

Voici un article de Nice sur promesses et $ q

UPDATE:

Pour votre information, $http le service lui-même renvoie une promesse, donc $q n'est pas nécessairement requis dans ce scénario (et donc un anti-pattern ).

Mais ne laissez pas cela être la raison pour éviter de lire à propos de $ q et des promesses.

Donc, le code ci-dessus est équivalent à ce qui suit:

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

Vous pouvez utiliser la méthode $ q.all () également pour résoudre ce problème

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

dans la fonction d'appel

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

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

assurez-vous d’injecter $ q en tant que dépendance. J'espère que ça aide

9
akashrajkn

Votre fonction semble redondante. Utilisez simplement $http.get(url), puisque vous ne faites pas vraiment autre chose avant de l’utiliser de toute façon.

var url = 'foo/bar';

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

Ou si vous devez accéder à la promesse ultérieurement, affectez-la à une variable;

var promise = $http.get(url);

// some other code..

promise.then(function(data){
   //.. do something with data
});
5
Matt Herbstritt

Une façon typique de faire ce que vous voulez est comme suit:

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

Utilisé comme:

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