Как отследить выполнение setTimeout?

Добрый день.
Тем кто подписан на рассылку по школе интерфейсов наверняка получили письмо-заявку в котором были тестовые задания. Так я не рассчитываю пройти, но задание на JS интересно выполнить. Так есть код с описанием тут.

И вроде все понятно, но запнулся практически вначале. Так как уловный ответ приходит с задержкой по setTimeout, а к тому времени for отрабатывает все три запроса (там три URL), а потом уже идет обработка в callbak.

Сам вопрос: так как setTimeout убрать нельзя, то каким образом зацепиться за callback в нем синхронно на три запроса?
  • Вопрос задан
  • 405 просмотров
Пригласить эксперта
Ответы на вопрос 2
DIITHiTech
@DIITHiTech
Fullstack javascript developer
Так? Или что там надо...
function getData(url, callback) {
           var RESPONSES = {
               '/countries': [
                   {name: 'Cameroon', continent: 'Africa'},
                   {name :'Fiji Islands', continent: 'Oceania'},
                   {name: 'Guatemala', continent: 'North America'},
                   {name: 'Japan', continent: 'Asia'},
                   {name: 'Yugoslavia', continent: 'Europe'},
                   {name: 'Tanzania', continent: 'Africa'}
               ],
               '/cities': [
                   {name: 'Bamenda', country: 'Cameroon'},
                   {name: 'Suva', country: 'Fiji Islands'},
                   {name: 'Quetzaltenango', country: 'Guatemala'},
                   {name: 'Osaka', country: 'Japan'},
                   {name: 'Subotica', country: 'Yugoslavia'},
                   {name: 'Zanzibar', country: 'Tanzania'},
               ],
               '/populations': [
                   {count: 138000, name: 'Bamenda'},
                   {count: 77366, name: 'Suva'},
                   {count: 90801, name: 'Quetzaltenango'},
                   {count: 2595674, name: 'Osaka'},
                   {count: 100386, name: 'Subotica'},
                   {count: 157634, name: 'Zanzibar'}
               ]
           };

           setTimeout(function () {
               var result = RESPONSES[url];
               if (!result) {
                   return callback('Unknown url');
               }

               callback(null, result);
           }, Math.round(Math.random * 1000));
       }

       /**
        * Ваши изменения ниже
        */
       
       var requests = ['/countries', '/cities', '/populations'];
       var responses = {}; //, counter=0;

       for (var i = 0; i < 3; i++) {
           var _request = requests[i];

           var callback = function(request){
               return function (error, result) {

                   responses[request] = result;

                   var i, j;

                   if (Object.keys(responses).length == 3) { //or counter++==3
                       var c = [], cc = [], p = 0;

                       for (i = 0; i < responses['/countries'].length; i++) {
                           if (responses['/countries'][i].continent === 'Africa') {
                               c.push(responses['/countries'][i].name);
                           }
                       }

                       for (i = 0; i < responses['/cities'].length; i++) {
                           for (j = 0; j < c.length; j++) {
                               if (responses['/cities'][i].country === c[j]) {
                                   cc.push(responses['/cities'][i].name);
                               }
                           }
                       }

                       for (i = 0; i < responses['/populations'].length; i++) {
                           for (j = 0; j < cc.length; j++) {
                               if (responses['/populations'][i].name === cc[j]) {
                                   p += responses['/populations'][i].count;
                               }
                           }
                       }

                       console.log('Total population in African cities: ' + p);
                   }
               }
           }(_request);


           getData(_request, callback);
       }


Вообще такие задачи красиво решаются с Promise.all - сам код подсчета не писал

var requests = ['/countries', '/cities', '/populations'];
       var responses = {};

       function load(request){
           return new Promise(function(resolve,reject){
               getData(request,function(error, result){
                    if(!error){
                        resolve(result);
                    }else{
                        reject (error);
                    }
               })
           });
       }

       function getPopulation(state){

           return Promise.all(requests.map(function(request){
               return load(request);
           })).then(function(data){
               //console.log(arguments);
               var countries=data[0],
                   cities=data[1],
                   populations=data[2],
                   result;

               console.log(countries,cities,populations);

               //calc here for state

               return result;

           },function(error){
               console.warn("Data error",error);
           });
       }

       getPopulation("Africa").then(console.log);
Ответ написан
dshster
@dshster
Javascript, Frontend
Мне кажется в таких случаях используют обещания, например, в ангуляре $q.all, куда передаётся массив обещаний и который срабатывает после того, как все обещания выполнятся.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы