2015-12-17 5 views
0

У меня есть функция, выполняющая рекурсивные вызовы. Структура выглядит следующим образом:

var getData = function(data){ 
    makeDbCall().then(function(response){ 
    if(response.something === someCondition){ 
     foreach(object in response) 
     getData(object); //calls itself over and over 
     } 
    } 
) 
}; 

общая идея (чтобы избежать от темы) является, скажем, получить все отели в городе, все номера в этих гостиницах, вся мебель в этих комнатах и ​​т.д. нормальный $ q.all Еогеасп вызов что-то вроде this - функция определяет:

var promises = []; 

, а затем возвращает $ q.all:

return $q.all(promises); 

Моя проблема заключается в том, что я не знаю, гдеreturn $ q.all from - если я верну его из «getData», он вернется на первую итерацию рекурсии, и (как я понимаю) может не включать последующие итерации, если начальные вызовы разрешаются до того, как новые будут нажаты.

Если я верну его после вызова getData(), я получаю ту же проблему, потому что, как мы все знаем, javascript продолжается, не дожидаясь вызовов, если мы не отложим их.

Я понимаю, что этот вопрос расплывчатый, и я полностью в порядке с неопределенным ответом. Я просто пытаюсь понять, нет ли у меня чего-то абсолютно простого или если это невозможно. (Я знаю, как это сделать очень грязно, но мне бы очень хотелось использовать $ q.all как-то).

Here is the actual function that I am trying to wait for with call values changed for sake of example.

+0

Вы хотите, чтобы функции 'getData' выполнялись последовательно или параллельно? Возвращают ли функции 'getData' обещания? – georgeawg

+0

Параллельный. В противном случае я бы просто связал их, как предложил Витторе. makeDbCall() автоматически обещает, будет ли его http или Restangular, getData CAN возвращать $ q.all (обещания), вопрос в том, нужно ли это делать. Я думаю, что я просто сделаю это «гетто» и сравню счет с возвращаемой длиной списка объектов. – VSO

ответ

1

Я пытался что-то по вложенности резолюции обещание как следующее:

function getData(){ 
    return new Promise((resolve, reject)){ 
    for(let item of response){ 
     getData(item).then((res)=>{ 
     resolve(res); 
     },(err)=>{ 
     reject(err); 
     }); 
    } 
    } 
} 

Хитрость заключается в том, чтобы использовать обещание каждый раз, когда вы можете. Таким образом, вы можете иметь разрешение вашего обещания на высшем уровне только тогда, когда ребята также разрешены, чтобы вы могли выполнить асинхронную рекурсию.

+0

Спасибо за ответ. Я не знаю, как это отличается от назначения вызова переменной и нажатия ее в массив обещаний. Может быть, я слишком задумываюсь, и все это будет цеплять. Тестирование. – VSO

1

Одна из вещей, которые вы могли бы сделать, это цепи обещаний в исходном массиве обещаний, и использовать карту, чтобы получить обещания для каждого элемента массива, т.е. рассмотреть этот snipet

function getHotels(city) { return ajaxPromise ... } 
function getRooms(hotel) { ... } 
function getFurniture(room) { ... } 
function showUI(furniture) { ... } 

getHotels(city).then(function(hotels) { 
    return $q.all(hotels.map(h => getRooms(h))) 
}).then(function(hotelRooms) { 
    return $q.all(hotelRooms.map (hr => getFurniture(hr))) 
}).then(showUI) 
+0

Я мог бы это сделать, но, насколько я понимаю, это будет намного медленнее, так как это не так быстро, как спам. Цените ответ! – VSO

1

Для начала ---

Эта методика устарела

app.factory('json',function($q,$http){ 
    return function(files){ 
     var promises = []; 
     angular.forEach(files, function(file){ 
      var deffered = $q.defer(); 
      $http({ 
        url : file, 
        method: 'GET' 
      }).success(function(data){ 
        deffered.resolve(data); 
      }).error(function(error){ 
        deffered.reject(); 
      }); 
      promises.push(deffered.promise); 
     }) 
     return $q.all(promises); 
    } 
}); 

Методы $http.success и .error являются устаревшим. Для получения дополнительной информации см. AngularJS $http Service API Reference.

Предпочтительный способ:

app.factory('json',function($q,$http){ 
    return function(files){ 
     var promises = []; 
     angular.forEach(files, function(file){ 
      var promise = 
       $http({ 
         url : file, 
         method: 'GET' 
         }) 
      promises.push(promise); 
     }) 
     return promises; 
    } 
}); 

Вы можете обрабатывать каждый из возвращенных обещаний по отдельности или использовать $q.all. Следует иметь в виду, что $q.all is не упруго. Первое обещание отклонить будет пропустить метод .then, и только первый отказ будет пойман методом .catch.

var promiseList = json(files); 

$q.all(promiseList).then (function (responseList) { 
    //executes only if all promises ok 
    $scope.dataList = doSomethingWith(responseList); 
}). catch (error) { function (error) 
    //executes with first error 
    //log error 
}); 

Чтобы обработать обещание по отдельности:

promiseList[0].then (function (result) { 
        //save data 
        $scope.dataList[0] = result.data; 
      }).catch (function (error) { 
        //log error 
      }); 

Обратите внимание, что .then и .catch методы возвращают данные иначе, чем .success и .error методов.

Смежные вопросы