LINUX.ORG.RU

Как работают таймеры в Javascript?

 ,


0

1

Для тестов мне нужно делать таймауты, чтобы между вызовами функций была небольшая задержка.
Как я понимаю, в JS нет прямого аналога sleep и для пауз надо использовать setTimeout, который как я понял асинхронный и суть аналог sleep &
Но я тогда не понимаю, почему этот код выполняется последовательно и выводит 1 2 3, а не 3 2 1 (даже просмотр «Call stack, heap, queue, event loop - Talk.JS » ничего не прояснил)

function m()
{
    setTimeout(console.log("1"), 10000);
    setTimeout(console.log("2"), 5000);
};
function n()
{
    console.log("3");
};

m();
n();


Просьба без углублений в промисы и прочие колбэки, я ненастоящий сварщик

★★★★★

setTimeout(console.log(«1»), 10000);

Потому что ты в сеттаймаут передаёшь результат выполнения console.log(«1»);

Твой код аналогичен:

var res = console.log("1");
setTimeout(res, 10000);

Заверни вызовы консольлога «function() { }».

ChALkeR ★★★★★ ()
Ответ на: комментарий от zolden

code in the alternate syntax is a string of code you want to execute after delay milliseconds

Где ты у себя string нашёл? И да, лучше так не делать, а использовать всё же функцию.

Psych218 ★★★★★ ()
Ответ на: комментарий от Psych218

Аа, это значит про навороты типа setTimeout(«function(» + parameter + ")",4000);

А блокирующий/синхронный sleep в JS вообще никак невозможен?

zolden ★★★★★ ()
Ответ на: комментарий от zolden
await

. Блокирует функцию, в которой находится, позволяя идти остальным. Разве нужно что-то большее?

Костыли ранжируются от бизи-wait'ов до синхронного xhr-запроса на sleep-as-a-service.

x3al ★★★★★ ()
Ответ на: комментарий от Deleted

Вот тебе фаталити, которое я буду использовать:

function sleep( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration * 1000){ /* Muahahahahahaha */ } 
}

zolden ★★★★★ ()
Ответ на: комментарий от Shadow

Не подходят, в виду специфики тестового окружения

zolden ★★★★★ ()
Ответ на: комментарий от umren

Да, уже весь монитор заплевал с этой, ска, асинхронностью. Блокирующий sleep тоже не помог отцу русской демократии, а десятки вложенных setTimeout что-то меня совсем не привлекают

zolden ★★★★★ ()
Ответ на: комментарий от zolden

Заверни setTimeout в Promise, дальше работай с ним как с Promise либо через yield (нативно в последней ноде)/await (babel). Вкладывать необязательно.

x3al ★★★★★ ()
Ответ на: комментарий от x3al

А можно пример?
На самом деле setTimeout это вариант в лоб, возможно есть более правильное решение.
Вот условный код:

QUnit.test( "test1", function( assert ) {
   someAsyncOpenFunction();
   setTimeout(function()
             {
               //get правильно срабатывает только завершения someAsyncOpenFunction(), задержка подобрана эмпирически
               var property1 = getProperty1();
               assert.ok(property1, "Property1 is correct");
             }, 2000);
   someAsyncCloseFunction();
   });

QUnit.test( "test2", function( assert ) {
   someAsyncOpenFunction();
   setTimeout(function()
             {
               var property2 = getProperty2();
               assert.ok(property2, "Property2 is correct");
             }, 2000)

   someAsyncCloseFunction();
   });
});
...
QUnit.test( "testN", function( assert ) {
   someAsyncOpenFunction();
   setTimeout(function()
             {
               var propertyN = getPropertyN();
               assert.ok(propertyN, "PropertyN is correct");
             }, 2000)

   someAsyncCloseFunction();
   });
});


Это ES5 и чисто клиентский код, ноды тут нет вообще никак. Применим ли babel в такой ситуации?

zolden ★★★★★ ()
Ответ на: комментарий от zolden

UI пользователя не нужна синхра
Как и сокет-серверу и демону и API-серверу

mystery ★★ ()
Ответ на: комментарий от x3al

Я правильно понимаю, что можно просто первым скриптом подключить bluebird.min.js а дальше можно изо всех сил фигачить на ES6?

zolden ★★★★★ ()
Ответ на: комментарий от zolden
function sleep (time) {
  return new Promise(function(resolve,reject){
    setTimeout(function(){
      resolve();
    }, time);
  });
};

Всё, можешь делать await sleep(time); и оно остановит эту функцию на time.

x3al ★★★★★ ()
Ответ на: комментарий от zolden

Если браузер не умеет в ES6 — нет. bluebird даёт более быстрые Promise, немного удобств и раннер для генераторов, позволяющий пользоваться ими как async/await, но сами генераторы — es6-фича.

x3al ★★★★★ ()
Ответ на: комментарий от mystery

Зачем лишние евалы? Тем более это ещё и не везде работает.

ChALkeR ★★★★★ ()
Ответ на: комментарий от x3al

Только я подумал что всё понял, но вдруг опять всё запуталось...
У меня в общем-то нет браузера как такового, там почти голый несвежий webkit.
Так какой смысл тогда в babel если у меня нет поддержки ES6?

И ещё вопрос про таймауты.
Я правильно понимаю, что какбэ синхронный таймер на основе Date(), упомянутый выше блокирует и главный поток и асинхронная функция, вызванная до его начала замораживается? А значит смысла в таком слипе нет

zolden ★★★★★ ()
Ответ на: комментарий от zolden

Я правильно понимаю, что какбэ синхронный таймер на основе Date(), упомянутый выше блокирует и главный поток и асинхронная функция, вызванная до его начала замораживается? А значит смысла в таком слипе нет

Ну, ты хотел синхронный sleep() — ты получил его. Про главный поток повеселило — в JS по умолчанию других потоков просто нет (не считая всяких webworker'ов в клиентском).

x3al ★★★★★ ()
Ответ на: комментарий от x3al

Ещё раз. babel. даст. на. выхлопе. es5

Я, честно говоря, так и не понял каким концом его прикрутить к моему случаю.
У меня просто один js файл в блокноте, у меня нет ноды, серверной части и прочих bower
По твоей ссылке упоминается только подключение bluebird

zolden ★★★★★ ()
Ответ на: комментарий от zolden

У меня просто один js файл в блокноте, у меня нет ноды, серверной части и прочих bower

https://babeljs.io/repl/#?evaluate=true&lineWrap=false&presets=es2015...

Если лень поставить ноду (на девел-машину) — держи.

x3al ★★★★★ ()
Последнее исправление: x3al (всего исправлений: 1)
Ответ на: комментарий от x3al

на девел-машину

Да я просто не разработчик, потому и нет ни девел машины, ни билд процесса, ни нод, ни прочих модных штук, поэтому приходится выкручиваться. Благо хоть успел книжку по JS почитать три дня.
За онлайн конвертер спасибо, будем попробовать

zolden ★★★★★ ()
Последнее исправление: zolden (всего исправлений: 1)
Ответ на: комментарий от zolden

Присваиваешь setTimeout, отчищаешь
А потом только будет твой код выполняться
Или так:

end = new Date().getTime() + 1000
do {} while(new Date().getTime() < end)
<1 sec elapsed>

mystery ★★ ()
Последнее исправление: mystery (всего исправлений: 1)
Ответ на: комментарий от x3al

Разве resolve() возвращает callback?
setTimeout принимает callback, достаточно просто передать resolve, без выполнения
Его выполнить сам setTimeout

mystery ★★ ()
Ответ на: комментарий от mystery

А потом только будет твой код выполняться

То есть с указанным синтаксисом у нас получается синхронный код? Где про это можно почитать?

zolden ★★★★★ ()
Ответ на: комментарий от mystery

Поставь и нормально интерпртируй код

Я правильно понимаю, что я смогу в командной строке подсунуть мой файл и нода сгенерирует мне новый файл в ES5 совместимом виде, а его я уже должен подключать на тестовой странице?

zolden ★★★★★ ()
Ответ на: комментарий от mystery

Оно ж внутри лямбды (бесполезной, но всё же), поэтому всё ок. Конечно, всё это можно записать как const sleep = (time) => new Promise((resulve, reject) => setTimeout(resolve, time));

x3al ★★★★★ ()
Ответ на: комментарий от zolden

Не надо передавать в setTimeout строку. Алсо, твой код не синхронный.

Мой — тоже, но await позволяет писать в синхронном стиле.

x3al ★★★★★ ()
Последнее исправление: x3al (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.