Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как совместить setTimeout и цикл for? (https://javascript.ru/forum/misc/65503-kak-sovmestit-settimeout-i-cikl.html)

vlad35 22.10.2016 18:19

Как совместить setTimeout и цикл for?
 
Здравствуйте, уважаемые форумчане! Есть div, который должен менять фон через каждую секунду. Теперь нужно, используя цикл for при каждом прохождении цикла сделать задержку каждого цвета на одну секунду с помощью setTimeout.
Дело в том, что цикл for выдает только последнее прохождение и не хочет задерживаться на каждом цвете. Поискал ответ в интернете, пришел к такому написанию скрипта:

<div style="width:300px; height:300px; background-color:red;" id="col"></div>
<script type="text/javascript">
var color = ["green", "blue", "red", "orange"];
var el = document.getElementById('col');
var max = color.length-1;

for(var i=0; i<=max; i++) {
(function(i){
setTimeout(function(){
el.style.background = color[i];
}, 1000);
})(i);
}
</script>

Но он тоже почему-то не работает. Подскажите, пожалуйста, как все-таки в моем скрипте совместить for и setTimeout.

Aetae 22.10.2016 18:33

Как? Никак.
Цикл выполняется сейчас и только сейчас, таймаут выполняется потом.

Таймаут должен вызывать функцию, которая вызывает следующий таймаут.

destus 22.10.2016 19:38

vlad35,
как вариант...
<div style="width:300px; height:300px; background-color:red;" id="col"></div>
	<script>
	let color = ["green", "blue", "red", "orange"],
	el = document.querySelector('#col'),
	requests = color.reduce((promiseChain, item) => {
		return promiseChain.then(() => new Promise(resolve => {
		  setTimeout(() => (el.style.background = item) && resolve(), 1000)
		}));
	}, Promise.resolve());	
	</script>

Vlasenko Fedor 22.10.2016 19:58

<div style="width:300px; height:300px; background-color:red;" id="col"></div>
<script>
const el = document.getElementById('col');
let iterator = next();
function* next() {
const arr = ["green", "blue", "red", "orange"];
  for (var i = 0; i <= arr.length;) {
    yield arr[i++];
  }
}
  (function newBackground() {
    let color = iterator.next().value;
    if (color) {
      el.style.background = color;
      setTimeout(newBackground, 1000);
    }
  }());
</script>

песочница
но зачем вам это, есть более простые решения данного функционала

Aetae 22.10.2016 20:02

Poznakomlus, годный овермайнд.))

Vlasenko Fedor 22.10.2016 20:13

Aetae,
особо не понял зачем ТС эти варианты
http://www.cyberforum.ru/javascript-...ad1830841.html

рони 22.10.2016 20:40

:)
<div style="width:300px; height:300px; background-color:red;" id="col"></div>
  <script>
  var color = ["green", "blue", "red", "orange"],
  el = document.querySelector('#col');
  (function f() {
   var item = color.shift();
   item && (el.style.background = item) && setTimeout(f, 1000)
  }())
  </script>

Vlasenko Fedor 22.10.2016 20:57

рони,
Цитата:

Сообщение от vlad35
нужно, используя цикл for

:)
Цитата:

Сообщение от vlad35 (Сообщение 432615)
совместить for и setTimeout.


рони 22.10.2016 21:18

Poznakomlus,
ок. но но зачем усложнять
Цитата:

Сообщение от Aetae
Цикл выполняется сейчас и только сейчас, таймаут выполняется потом.

Таймаут должен вызывать функцию, которая вызывает следующий таймаут.


Vlasenko Fedor 22.10.2016 21:38

Цитата:

Сообщение от рони
Цикл выполняется сейчас и только сейчас

может стоит задача написания кода с использованием генераторов
Цитата:

Сообщение от Poznakomlus
особо не понял зачем ТС эти варианты


Aetae 22.10.2016 21:40

Цитата:

Сообщение от рони (Сообщение 432630)
Poznakomlus,
ок. но но зачем усложнять

Потому что он может.)

Тс хотел for - он получил for.)

рони 22.10.2016 22:30

Aetae,
как я понимаю решение совмещения for и setTimeout
<div style="width:300px; height:300px; background-color:red;" id="col"></div>
 <script type="text/javascript">
 var color = ["green", "blue", "red", "orange"];
 var el = document.getElementById('col');
 var max = color.length-1;

 for(var i=0; i<=max; i++) {
 (function(i){
 setTimeout(function(){
 el.style.background = color[i];
 }, 1000*i);
 })(i);
 }
 </script>

Aetae 22.10.2016 23:17

рони, жесть.))

vlad35 23.10.2016 20:22

Спасибо Всем, кто ответил, все прочитал и принял к сведению. Я только несколько дней как взялся изучать JavaScript, поэтому извините за нелепый вопрос.

Aetae 24.10.2016 00:44

vlad35, тогда тебе только этот вариант. На остальные не смотри, это просто извращенные развлечения.)

MallSerg 24.10.2016 05:26

Цитата:

Сообщение от Aetae (Сообщение 432715)
vlad35, тогда тебе только этот вариант. На остальные не смотри, это просто извращенные развлечения.)

имхо: Тот вариант это рекурсия с созданием замыкания при этом еще долго живущая т.к. ссылка на функцию живет в SetInterval. Интерпретатору приходится каждый раз на вызов создавать контекст(окружение) для исполнения таких функций что просто ужасно для производительности. Тут как раз и нужно использовать чуть ли не единственную полезную фичу из ES6 стрелочные функции которые исполняются в текущем контексте.

что то вроде
<div style="width:300px; height:300px" id="col"></div>
<script>
	var color = [];
	var el = document.querySelector('#col');
	var f=()=> (el.style.background = color.shift()) && setTimeout(f,100);
	
+function(){  // заполняет массив цветов
var i=0,R=G=0,B=15,t=P=>P.toString(16),P=()=>color.push("#"+t(R)+t(G)+t(B));
while(i<16)P(R=i++);while(i>0)P(B=i--);while(i<16)P(G=i++);
while(i>0)P(R=i--);while(i<16)P(B=i++);while(i>0)P(G=i--);}();f()
</script>

vlad35 24.10.2016 10:06

Спасибо всем за участие, очень помогли! Я пока новичок в JavaScript, поэтому вопросы могут быть глупыми, извините!

Vlasenko Fedor 24.10.2016 11:38

Цитата:

Сообщение от Aetae
vlad35, тогда тебе только этот вариант

shift удаляет элемент с индексом 0 и сдвигает остальные элементы на один вниз
не совсем красиво то для данной задачи :nono:

Aetae 24.10.2016 14:41

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


Часовой пояс GMT +3, время: 21:10.