Angular.forEach и объекты

Проблема:

Я делаю (что, по-моему, но, возможно, нет), просто angular.forEach над массивом, а затем используя $resource, чтобы сделать вызов на основе каждого возвращаемого значения. Результатом каждого вызова является объект, как я ожидаю. Но я не могу заставить эти объекты гармонично объединиться в том, как демонстрируется angular.forEach документация.

Но сначала, какой-то код, который работает, а затем посмотрите на код, который терпит неудачу.

Работы

var uniqueIds = {};
angular.forEach(object, function(key, value){
    this.push(key.uniqueIds);
}, uniqueIds);
console.log(uniqueIds)
// uniqueIds equals the expected array

Не удается

Здесь, где вещи становятся хитрыми. Теперь, в следующем примере, внутри angular.forEach есть вызов $resource.

angular.forEach(array, function(index){
    Resource.query({id:index}, function(result){
        console.log(result)
        // returns the expected object, 
        // but, as expected, I can't access the object outside the async call
    });
    console.log(result);
    // result is undefined
 });

Учитывая асинхронность, кажется, что обещание может решить проблему. Но это не так... Я все еще в асинхронном разговоре. Не назначается result $scope. Короче говоря, я не могу получить значение вне Resource.query.

Что мне нужно делать?

Мне нужен возвращаемый объект каждого вызова $resource, чтобы добавить один объект (используя angular.extend? Я пробовал это) так же, как angular.forEach создал массив. Я пробовал много разных подходов, большинство из них основывалось на ответах на общие асинхронные вопросы, заданные здесь, но до сих пор безрезультатно. Я уверен, что это проблема с получением значения из вызова $resource, но как это сделать в этом случае, я немного озадачен.

Ответы

Ответ 1

Что-то вроде этого?

var promises = [];

angular.forEach(array, function(index) {
  promises.push(Resource.query(...));
});

$q.all(promises).then(function(result1, result2, result3 ...) {
  // do stuff with result1, result2 ... or
  // var results = Array.prototype.slice.call(arguments);
});

Ответ 2

Angular документация имеет очень хороший пример для этого

var values = {name: 'misko', gender: 'male'};
var log = [];
angular.forEach(values, function(value, key) {
    this.push(key + ': ' + value);
 }, log);

Ответ 3

.query возвращает ссылку на массив, которая заполняется данными при завершении xhr. Поскольку, возможно, id является уникальным идентификатором, запрос возвращает массив с одним элементом, поэтому я предлагаю вам вместо этого использовать .get.

В любом случае, если вы все еще намерены использовать .query, вы можете сделать что-то вроде:

var arrays = [];
angular.forEach(array, function(index){
    arrays.push(Resource.query({id:index}, function(result){
        console.log(result)
        // returns the expected object, 
        // but, as expected, I can't access the object outside the async call
    }));
    console.log(result);
    // result is undefined
});

$scope.$watch(function () {
    return arrays;
}, function (arrays) {
    angular.forEach(arrays, function (array) {
       angular.forEach(array[0], function () {
          //Do something with the object fields
       });
    });
});

Как вы видите, код выглядит довольно плохо...

Для достижения лучшего результата вы можете использовать:

var objects = [];
angular.forEach(array, function(index){
    objects.push(Resource.get({ id:index });
});

$scope.$watch(function () {
    return objects;
}, function (objects) {
    angular.forEach(objects, function (obj) {
       angular.forEach(obj, function () {
          //Do something with the object fields
       });
    });
});

Еще лучше, если вы позволите AngularJS сделать $watch, присвоив objects свойству $scope.