2015-05-27 2 views
1

Я смущен, у меня есть setTimeout(), который имеет функцию $ .each для анимации каждого слайдера каждые 5 секунд. (Это происходит из-за другой SetTimeout() внутри функции $ .each.

Теперь я задаюсь вопросом, как я могу запустить мой populateGraph() функции после SetTimeout и $ .each завершены Я попытался следующие, но он работает одновременно

setTimeout(function() { 
    $.each(data, function(i, v) { 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 
     }, 500 + (500 * i)); 
    }); 
    populateGraph(); 
}, 500); 

Спасибо!

ответ

2

Вы называете populateGraph() после вашего последний SetTimeout вызов, фокус в том, зная, какой из них ваш последний:

setTimeout(function() { 
    var currentCount = data.length; 
    $.each(data, function(i, v) { 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 

      //decrease currentCount by one 
      currentCount--; 

      //if currentCount is at 0, then we know we've completed the last setTimeout 
      if(!currentCount) { 
       populateGraph(); 
      } 
     }, 500 + (500 * i)); 
    }); 

}, 500); 
+0

Также очень хорошее решение! – Notflip

1

Я думаю, вам нужно использовать $.Deferred(), как и

setTimeout(function() { 
    var deferred = $.Deferred(), 
     len = data.length; 

    $.each(data, function(i, v) { 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 

      if (i + 1 === len) { 
       deferred.resolve(); 
      } 
     }, 500 + (500 * i)); 
    }); 

    deferred.done(function() { 
     populateGraph(); 
    }); 
}, 500); 
2

Попробуйте это:

setTimeout(function() { 
    var d= $.Deferred(); 
    var c=data.length; 
    $.each(data, function(i, v) { 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 

     if (i+1==c) d.resolve(); 
     }, 500 + (500 * i)); 
    }); 

    d.done(function() { 
     populateGraph(); 
    }); 
}, 500); 
+0

Что такое $ .deffered()? – Notflip

+1

весь новый мир ..... https: //api.jquery.com/jquery.deferred/ –

+0

Это менее нервный, что точно. Заглядывая в отложенный – Notflip

1

Просто запланировать 500 мс после последнего?

setTimeout(function() { 
    $.each(data, function(i, v) { 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 
     }, 500 * i); 
    }); 
    setTimeout(populateGraph, 500 * data.length); 
}, 500); 
+0

Это очень умно! Не думал бы об этом. Спасибо! – Notflip

+2

@Notflip ** Нет !!! **. может быть GAP между временем выполнения и расчетными временами! –

+0

@RoyiNamir это не имеет значения, если это 500 или 550 :) Было важно, чтобы функция populateGraph() запускалась после завершения циклов. – Notflip

0

Кажется, что и нужно эмиттер, чтобы помочь U из ...

setTimeout(function() { 
    var emitter = new SuperEmitter(),//Create new super emitter 
     emittors = []; 
    $.each(data, function(i, v) { 
     emittors.push(v.id);//Collect all emittors that populateGraph() should wait 
     setTimeout(function() { 
      $(".slider#" + v.id).slider("value", globalcoachscores[i]); 
      emitter.emit(v.id);//Emit emittor when one job is done 
     }, 500 + (500 * i)); 
    }); 
    emitter.on(emittors,function(){ 
     populateGraph(); 
    });//Set event job after all the jobs are done 
}, 500); 

и вот мой SuperEmitter конструктор:

// Super Emitter 
/** 
* Create a super emitter 
* 
* @constructor 
* @param {String} name - The name of the emitter. 
* @author Maplemx([email protected]) 
*/ 
function SuperEmitter(name){ 
    var waitors = [], 
     emittors = {}; 

    function tryEmittor(emittor,data){ 
     if (emittors[emittor]){ 
      data = mergeObjects(emittors[emittor],data); 
     } 
     for (var i = 0;i < waitors.length;i++){ 
      if (waitors[i]){ 
       var emittorIndex = waitors[i].wait.indexOf(emittor); 
       if (emittorIndex > -1){ 
        waitors[i].wait.splice(emittorIndex,1); 
        waitors[i].data = mergeObjects(waitors[i].data,data); 
       } 
       if (waitors[i].wait.length === 0){ 
        waitors[i].func(waitors[i].data); 
        waitors[i] = undefined; 
       } 
      } 
     } 
    } 
    function tryWaitors(waitorId){ 
     if (waitors[waitorId]){ 
      for (var emittor in emittors){ 
       var emittorIndex = waitors[waitorId].wait.indexOf(emittor); 
       if (emittorIndex > -1){ 
        waitors[waitorId].wait.splice(emittorIndex,1); 
        waitors[waitorId].data = mergeObjects(waitors[waitorId].data,emittors[emittor]); 
       } 
       if (waitors[waitorId].wait.length === 0){ 
        waitors[waitorId].func(waitors[waitorId].data); 
        waitors[waitorId] = undefined; 
        break; 
       } 
      } 
     } 
    } 

    /** 
    * Set new function into wait list 
    * 
    * @public 
    * @param {Array|*} emittors - The emittor(s) that the function wait for.(If emittor is not an Array, will turn it to an Array) 
    * @param {Function} func - The function todo when emittor is sent. 
    * @param {Object} [data] - The data want to send to the function. 
    */ 
    this.on = function on(emittors,func,data){ 
     if (!(emittors instanceof Array)){emittors = [emittors];} 
     var waitorId = waitors.push({ 
      wait: emittors, 
      func: func, 
      data: data, 
     }) - 1; 
     tryWaitors(waitorId); 
    } 

    /** 
    * Send an emittor 
    * 
    * @public 
    * @param {*} emittor - The emittor to be sent. 
    * @param {Object} [data] - The data want to send to the functions which are waiting for the emittor.(The data here have higher priority than the data given when functions are put into wait list.) 
    * @param {Boolean} [stay=true] - Tell if you want the emittor stay in memory, so that functions which are put into wait list later than emittor which are sent can also be activated by those emittor. If "stay" is true, you have to "unemit" the emittor manual. 
    */ 
    this.emit = function emit(emittor,data,stay){ 
     if (typeof(stay) === 'undefined'){stay = true;} 
     if (stay){ 
      emittors[emittor] = data; 
     } 
     tryEmittor(emittor,data); 
    } 

    /** 
    * Erase an emittor (If "stay" is set false when emittor is sent, you don't need to erase it, because the emittor was not saved in memory) 
    * 
    * @public 
    * @param {*} emittor - The emittor to be erased. 
    */ 
    this.unemit = function unemit(emittor){ 
     if (emittors[emittor]){ 
      delete emittors[emittor]; 
     } 
    } 
} 
+0

Wowie! Я должен буду прочитать это медленно! Никогда не слышал об этом подходе :) – Notflip

+0

@Notflip да, проблема с сообщением была также проблемой, которая беспокоила меня при выполнении асинхронного программирования ... так что я нашел этот способ решить эту проблему ... – Maplemx

0

Я рекомендую использовать библиотеку Q promise здесь:

var promise = Q(); 
$.each(data, function(i, v) { 
    // since we construct this out of a .then callback, it's relative 
    // to when this setup loop ran, not to the previous iteration 
    var delay_until = Q.delay(500*i); 

    // add to the promise chain 
    promise = promise.then(function() { 
     return delay_until; 
    }).then(function() { 
     $(".slider#" + v.id).slider("value", globalcoachscores[i]); 
    }); 
}); 
promise.then(populateGraph); 

Установив задержку, как это сделал я, вы получаете лучшее из обоих миров:

  • Если что-то заставляет страницу отставать, она догонит, а не добавлять к общему времени анимации
  • Порядок анимации по-прежнему будет гарантированно, так как цепь должна быть выполнена в порядке
Смежные вопросы