AngularJS $http возвращает данные об успешном обратном вызове

Всем привет :) Вот такая проблема. Я делаю угловое приложение с:

  • фабрика для доступа к API с $http, который извлекает массив объектов с сервера

    getObjectsFromApi : function(){
        return $http({
            url: 'http://path/to/the/api/',
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            }
        })       
    },
    
  • и служба для вычисления полученных данных и их ввода в контроллеры.

    this.getObjectsFromService = function(){
        var objects = [];
    
        ObjectFactory.getObject()
        .success(function(data, status){
            console.log("Successfully got objects !");
            objects = data;
        })
        .error(function(data, status){
            console.log("Fail... :-(");
        });
    
        return objects;
    };
    

Проблема в том, что когда я возвращаю объекты, он не возвращает никаких данных. Как я могу вернуть данные обратного вызова $http в этой функции getObjectsFromService?

Спасибо за помощь !


person Community    schedule 18.02.2015    source источник


Ответы (5)


Вы должны использовать обещания, что-то вроде этого должно помочь

this.getObjectsFromService = function(){
    var defer = $q.defer();

    ObjectFactory.getObject()
    .then(function(data){
        console.log("Successfully got objects !");
        defer.resolve(data);
    })
    .catch(function(data){
        console.log("Fail... :-(");
         defer.reject(data);
    });

    return defer.promise;
};

И теперь вы можете использовать эту функцию в другом месте, например:

var foo = function() {
    var objects = [];
    this.getObjectsFromService().then(function(data) {
        objects = data;
        //do rest of your manipulation of objects array here
    });
}

Нет другого способа вернуть объекты, это невозможно, потому что $http является асинхронным. Вам придется переработать остальную часть кода и адаптировать его к этому.

person IanDess    schedule 05.05.2016

var req = ObjectFactory.getObject();

req.success(function(data) {...}
req.error(function(data) {...}

Это сделает это за тебя

Затем переменная req будет обещанием, отправленным обратно с завода.

Изменить

Имейте в виду, что ваши данные не будут изменены до тех пор, пока обещание не будет разрешено, поэтому, если вы попытаетесь выполнить console.log(objects) до этого, он будет пустым.

person ribsies    schedule 18.02.2015
comment
Я пропустил свои объяснения: проблема в том, что я хочу вернуть данные, полученные от API, чтобы ввести их в контроллер. Другими словами, я хочу получить данные ответа, поместить их в свою переменную объектов и вернуть эту переменную. Так что извините за плохой английский... :-/ - person ; 18.02.2015
comment
Это решит и эту проблему. Замените свой код там, где стоит «...». - person ribsies; 18.02.2015

HTTP-запрос является асинхронным, что означает, что он завершается после возврата objects. Вместо этого верните обещание:

this.getObjectsFromService = function(){
    return ObjectFactory.getObject().catch(function(){
        console.log("Fail... :-(");
    });
}

потом

service.getObjectsFromService().then(function(resp) {
    console.log("Successfully got objects !", resp.data);
});
person noj    schedule 18.02.2015

Ваш код асинхронный. Когда вы возвращаете объекты, вы возвращаете исходный пустой массив. Вы не можете напрямую вернуть свой объект, но вместо этого вам нужно вернуть обещание (см. 3 возможности ниже)

Создав обещание

var deferred = $q.defer();

ObjectFactory.getObjectsFromApi()
    .success(function(data, status){
        console.log("Successfully got objects !");
        // Do stuff and resolve promise
        deferred.resolve(data);
     })
     .error(function(data, status){
         console.log("Fail... :-("));
         // Do stuff and reject promise
         deferred.reject(data)
     });

return deferred.promise;

Вы можете использовать цепочку промисов (используйте .then вместо .success и .error):
Примечание: при использовании then с обратными вызовами успеха и ошибки, а не методами успеха и ошибки, у вас есть только 1 аргумент, который является ответом объект

return  ObjectFactory.getObjectsFromApi()
    .then(function(response){
        console.log("Successfully got objects !");
        // Do stuff and chain full response headers or data
        return responseHeaders;
        // or
        // return responseHeaders.data;
     }, function(responseHeaders){
         console.log("Fail... :-("));
         // Do stuff and chain error (full response headers or data)
         return $q.reject(responseHeaders)
         // return $q.reject(responseHeaders.data);
     });

Или, если у вас нет бизнес-логики или нет причин вмешиваться в вашу фабрику, просто верните вызов $http напрямую:

return  ObjectFactory.getObjectsFromApi();
person Thomas Roch    schedule 18.02.2015
comment
У вас слишком много возвратов в вашем коде. Так не пойдет. - person ribsies; 18.02.2015
comment
Да, у меня был один возврат, который я случайно оставил, на первом примере. Остальное правильно. Если вы считаете, что возвратов слишком много, посмотрите на цепочку обещаний асинхронного программирования. - person Thomas Roch; 19.02.2015

Угловой ресурс $

Фабрика

getObjectsFromApi : function(){
    return $resource('http://path/to/the/api/', {}, 
    {
        get: {
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
            } 
        }
    })       
},

Оказание услуг

this.getObjectsFromService = function(){
    var objects = [];

    ObjectFactory.get().$promise.then(function(data) {
         objects = data;
         return objects;
    }).error(function(err) {
        throw err;
    });
};
person Harben    schedule 18.02.2015
comment
Это вернет пустой массив, вызов ObjectFactory является асинхронным. - person Thomas Roch; 18.02.2015