Подтвердить что ты не робот

Синхронный http-вызов в angularJS

У меня есть следующий сценарий: мне нужны данные с определенного URL-адреса. Я написал функцию, которая принимает параметр 'url'. Внутри функции у меня есть метод $http.get, который вызывает вызов URL. Данные должны быть возвращены вызывающей функции

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

Проблема заключается в следующем: $http.get является асинхронным, до получения ответа функция возвращает. Поэтому вызывающая функция получает данные как пустую строку. Как заставить функцию не возвращаться до тех пор, пока данные не будут получены из URL?

4b9b3361

Ответ 1

Взгляните на promises, чтобы преодолеть такие проблемы, потому что они используются повсюду в мире angular.

Вам нужно использовать $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;
}

Вот хорошая статья о promises и $q

UPDATE:

FYI, $http сама услуга возвращает обещание, поэтому $q необязательно требуется в этом сценарии (и, следовательно, anti-pattern).

Но не позволяйте этому пропустить чтение о $q и promises.

Таким образом, приведенный выше код эквивалентен следующему:

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

Ответ 2

Вы также можете использовать метод $q.all() для решения этой проблемы

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

в вызывающей функции

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

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

Обязательно введите $q в качестве зависимости. Надеюсь, что это поможет.

Ответ 3

Типичный способ сделать то, что вы хотите, выглядит так:

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

Используется как:

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

Ответ 4

Вы работаете, кажется излишним. Просто используйте $http.get(url), так как вы на самом деле ничего не делаете, прежде чем использовать его в любом случае.

var url = 'foo/bar';

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

Или, если вам нужно получить доступ к обещанию позже, просто назначьте его переменной;

var promise = $http.get(url);

// some other code..

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