2015-08-25 3 views
0

Я хочу выполнить запрос HTTP GET, который извлекает некоторые данные, а затем создать несколько «подзапросов» для выполнения на основе этих данных, а затем повторить этот цикл: big запрос, затем некоторые небольшие запросы, основанные на данных, возвращенных из большого. Тем не менее, я хочу, чтобы следующая итерация цикла начиналась только после все «подзапросов». Мой код до сих пор выглядит следующим образом:Promise.all, похоже, не ждет, пока все закончится

var end = w/e; // the amount of calls I want to make 
(function recursiveCall(index) { 
    $http.get('blahblahblah').then(function (response) { // "big" request 
     var requests = []; 
     for(var i = 0; i < whatever; i++) { 
      requests[i] = (function(reqIndex) { // fill the array with a series of (different) requests 
       return function() { 
        setTimeout(function() { 
         // use reqIndex to create a different request 
         $http.get('blahblahblah' + reqIndex /* some modification based on i */).then(function (data) { 
          // callback 
         }, function (data) { 
          // error 
         }); 
        }, 1000 * reqIndex); // need to pause between each req 
       } 
      })(i) 
     } 
     Promise.all(requests.map(function (req) { // execute the array of requests 
      return req(); 
     })).then(function (data) { // I want this to happen only after *all* the requests are done 
      // success! 
      console.log('all sub-requests done!'); 
      if(index === end) { 
       return 0; 
      } else { 
       recursiveCall(++index); // repeat with index + 1 
      } 
     }, function (data) { 
      // error :(
      console.log("error"); 
     }); 
    }, function (response) { 
     // error 
    }); 
})(0); 

Однако раздел Promise.all()then() кажется выполнить сразу же после того, как «большой» запрос возвращается с 200; он не ждет, пока все остальные будут выполнены. Почему это?

+0

Вы не наполняя 'requests' массив с обещаниями. Вам нужно обернуть setTimeout с обещанием и разрешить или отклонить его в методе обратного вызова http. – mguimard

+0

Я об этом подумал; тот факт, что 'setTimeout()' не возвращает обещание, но верно вещь внутри ('$ http.get()')? Остановляет ли 'setTimeout()' обертку 'Promise.all()' от ее обнаружения? – Bluefire

+1

Да. Создайте обещание перед setTimeout. Разрешите или отклоните его в обратном вызове http. Не забывайте немедленно возвращать обещание (после инструкции setTimeout) – mguimard

ответ

1

Вот пример кода, чтобы проиллюстрировать мой комментарий:

return new Promise(function(resolve, reject) { 
    setTimeout(function(){ 

     // Then, in the http callback 
     resolve(); // or reject depending on your stuff... 

    }, 1000); 
}); 

Если вы используете $ Q (в AngularJS приложение), пожалуйста, обратитесь к https://docs.angularjs.org/api/ng/service/%24q

+0

Спасибо! Это очень помогает. – Bluefire

+0

Быстрая вещь: похоже, нет никакой разницы между нативным 'Promise' и Angular' $ q'. Я что-то упускаю? – Bluefire

+0

Избегайте [antiprottern конструктора обещаний] (http://stackoverflow.com/q/23803743/1048572), если вы делаете больше, чем 'resolve()' внутри таймаута. Также у Angular уже есть обещанная версия 'setTimeout', поэтому вы должны просто использовать ее. – Bergi

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