Задержка выполнения сценария

по какой то причине скрипты и сценарии настроенные на вход пользователя в систему не отрабатывают сразу, а выполняются с задержкой в 5 минут

Обновлено 22.06.2019

вход в систему

Добрый день! Уважаемые читатели и гости крупного IT блога России Pyatilistnik.org. В прошлый раз я вас научил делать резервную копию файлов и папок с помощью утилиты Robocopy. Сегодня я хочу вам рассказать еще об одной ситуации, которая случилась в моей административной практике, а именно по какой то причине скрипты и сценарии настроенные на вход пользователя в систему не отрабатывают сразу, а выполняются с задержкой в 5 минут. Мне стало интересно разобраться в данной ситуации и естественно поправить время выполнения моих скриптов. Думаю, что найдутся люди, кто так же зададутся данным вопросом.

Описание ситуации

Есть терминальная RDS ферма построенная на базе операционной системы Windows Server 2012 R2, состоящая из 15 RDSH хостов. Для удобства пользователей использующих программу 1С, был настроен через групповую политику скрипт, который при входе пользователя в систему должен был подтянуть конфигурационный файл с необходимым списком баз 1С. Но получилась такая ситуация, что пользователь заходит, видит свой рабочий стол, открывает программу 1С и баз там нет, через 5 минут, перезапустив 1С они магическим образом появляются. Давайте разбираться, что это за задержка и как от нее избавится.

Откуда берется 5-ти минутная задержка

Оказывается с выходом операционных систем Windows Server 2012 R2 и Windows 8.1 компания Microsoft ввела некоторое изменение с применением сценариев и скриптов при входе пользователя в систему. После входа пользователя на компьютер под управлением Windows 8.1 и Windows Server 2012 R2 сценарии входа не запускаются в течение пяти минут. Такое поведение вызывает следующие симптомы:

  • Операции, выполняемые сценариями входа в систему, могут не отображаться на компьютерах под управлением Windows 8.1 и Windows Server 2012 R2 в течение пяти минут после входа пользователя в систему.
  • Ресурсы, предоставляемые сценариями входа в систему, могут быть недоступны пользователям на компьютерах под управлением Windows 8.1 и Windows Server 2012 R2 в течение примерно пяти минут после входа пользователей.

https://support.microsoft.com/en-gb/help/2895815/logon-scripts-do-not-run-for-five-minutes-after-a-user-logs-on-to-a-wi

Microsoft ввела данную задержку из-за того, чтобы улучшить ситуацию, когда большое количество скриптов, сценариев, выполняемых при логине пользователя в систему вступают в конфликтную ситуацию, что он даже не может попасть на свой рабочий стол. Данная настройка называется » Настроить задержку сценария входа (Configure Logon Script Delay)». По умолчанию она имеет значение в 5 минут, этого достаточно, чтобы пользователь вошел в систему, которая успела прогрузить все из автозагрузки, после чего к нему можно применять сценарии.

Как убрать 5-ти минутную задержку выполнения сценариев при входе в систему

Так как у вас есть домен Active Directory и вы все настройки выполняете через групповую политику, то откройте редактор групповой политики, найдите нужное вам организационное подразделение, создайте там политику или измените существующую. Нужная нам настройка находится в разделе компьютера, переходим по пути:

Конфигурация компьютера — Политики — Административные шаблоны — Система — Групповая политика — Настроить задержку сценария входа (Computer Configuration — Administrative Templates — System — Group Policy — Configure Logon Script Delay)

Настроить задержку сценария входа

Открываем политику «Настроить задержку сценария входа». Режимы работы:

  • Если стоит значение по умолчанию, то будет отложенное выполнение скриптов через 5 минут
  • Если выставлено значение отключено, то сценарии входа будут выполнятся сразу
  • Если поставите 0, то так же политика будет отключена и все будет выполняться сразу при входе, именно данный вариант и советует сама Microsoft
  • Так же вы можете выставить другое значение, вплоть до 1000 минут.

Настроить задержку сценария входа (Configure Logon Script Delay)

Сохраняем настройку и давайте посмотрим как будет применяться политика при входе пользователя Барбоскина на терминальную ферму. Для этого откройте журналы логов Windows. Нас будет интересовать журнал Microsoft-Windows-GroupPolicy/Operational. Зашел я на терминальный сервер в 18-42 минуты.

Событие 5324: Групповая политика получила уведомление Вход в систему от Winlogon для сеанса 11.

Код события ID 5324

Событие с кодом ID 5351: Сеанс групповой политики возвращается к WinLogon

Сеанс групповой политики возвращается к WinLogon.

Событие с кодом ID 4117: Начат сеанс групповой политики

ID 4117 Начат сеанс групповой политики

Событие с кодом ID 4117: Запуск обработки политики входа пользователя в систему для rootbarboskin.g. Идентификатор операции: {f61f8549-f12f-4306-a957-83000600000000}

/wp-content/uploads/2019/06/ID-4117-1.jpg»>ID 4117

Событие с кодом ID 5340: Режим обработки групповой политики: Фоновый асинхронный

Режим обработки групповой политики: Фоновый асинхронный

Событие с кодом ID: Попытка получения сведений об учетной записи

Попытка получения сведений об учетной записи

Событие с кодом ID 4017: Выполнение системного вызова для получения сведений об учетной записи

Выполнение системного вызова для получения сведений об учетной записи

Событие с кодом ID 5017: Системный вызов для получения сведений об учетной записи завершен. Вызов обработан за 0 мс.

Событие с кодом 5017

Событие с кодом ID 5320: Полученные сведения об учетной записи

Полученные сведения об учетной записи

Событие с кодом ID 4126: Групповая политика получает применимые GPO от контроллера домена.

Групповая политика получает применимые GPO от контроллера домена.

Событие с кодом ID 4257: Начинается скачивание политик

Начинается скачивание политик

Событие с кодом ID 5257: Политики успешно скачаны

Политики успешно скачаны

Событие с кодом ID 5216: Политики успешно сохранены в локальное хранилище данных

Политики успешно сохранены в локальное хранилище данных

Событие с кодом ID 5126: Групповая политика успешно получила применимые GPO от контроллера домена

Групповая политика успешно получила применимые GPO от контроллера домена

Событие с кодом ID 5312: Список применимых объектов групповой политики

Список применимых объектов групповой политики

Событие с кодом ID 5016: Завершена обработка расширения Scripts

Завершена обработка расширения Scripts

Событие с кодом ID 8001: Завершена обработка политики входа пользователя для barboskin.g за 1 с

Завершена обработка политики входа пользователя для barboskin.g за 1 с

Событие с кодом ID 5117: Сеанс групповой политики успешно завершен

Сеанс групповой политики успешно завершен

Вот такой набор событий, который показывает вам, как применяются групповые политики к вашему пользователю, уверен, что благодаря данным событиям вы легко сможете отслеживать, есть ли у вас задержки при обработке сценариев входа пользователя в систему. Теперь у вас не должно быть 5-ти минутных задержек. На этом у меня все, с вами был Иван Семин, автор и создатель IT портала Pyatilistnik.org,

При использовании скриптов часто бывает необходимость установки интервала выполнения между одной частью программы и другой. Это можно назвать паузами, но чаще они имеют название содержащие sleep и такая же команда есть в Powershell. Один из примеров использования таких задержек — это поисковики. Когда мы часто выполняем запросы к одному сайту может появится каптча и что бы этого избежать нужно использовать задержку.

Синтаксис командлета следующий:

Start-Sleep -Seconds 5

Кроме длительности задержки в секундах мы можем указывать миллисекунды:

sleep -Milliseconds 5

Sleep — это алиас на основную команду.

Параметров для минут и часов нет, но вы можете выполнять такие операции в качестве выражений:

$timeout = 2
Sleep -Second ($timeout * 60)

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

function Start-SleepMinutes ($Seconds, $Minutes, $Hours){
        if ($Seconds){Start-Sleep -Seconds $Seconds}
        elseif ($Minutes){Start-Sleep ($Minutes*60)}
        elseif ($Hours){Start-Sleep ($Hours*60*60)}
}
Start-SleepMinutes -Seconds 2

Более подробно о создании функций в Powershell мы писали раннее. 

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

$timer = @(1,2,3,4)
$timer | sleep

Такую команду можно использовать для подсчета роста использования ресурсов каким-нибудь процессом:

$result = Get-Process -Name chrome | Measure-Object -Sum WS
sleep 10
$result2 = Get-Process -Name chrome | Measure-Object -Sum WS
$result.Sum - $result2.Sum

Теги:

#powershell

В JS для работы с «планированием вызова» существуют два метода:

1

Метод setInterval

Позволяет вызывать функцию много раз, через определённый интервал времени:

Схема работы setInterval

setInterval(func, delay)

Где:

  • func – функция или строка кода для выполнения,
  • delay – интервал в миллисекундах (1000 = 1 секунда).

Стоит заметить, что вызываемая функция будет работать асинхронно.

Выполнение кода:

setInterval("alert('Прошла одна секунда');"}, 1000);

JS

Выполнение анонимной функции:

setInterval(function(){
	alert('Прошла одна секунда');
}, 1000);

JS

Вызов функции:

setInterval('showmessage', 1000);

function showmessage(){
	alert('Прошла одна секунда');
}

JS

Отмены выполнения

Чтобы остановить setInterval применяется метод clearInterval(id).

var interval_id = setInterval(function(){
	alert('Прошла одна секунда');
}, 1000);

...

clearInterval(interval_id);

JS

2

Метод setTimeout

Выполняет заданный код асинхронно только один раз, через заданный интервал времени.

Схема работы setTimeout

Синтаксис:

setTimeout(func, delay)

Где:

  • func – функция или строка кода для выполнения,
  • delay – интервал в миллисекундах (1000 = 1 секунда).

Выполнение кода:

setTimeout("alert('1-секундная задержка прошла');", 1000);

JS

Выполнение анонимной функции:

setTimeout(function(){
	alert('1-секундная задержка прошла');
}, 1000);

JS

Вызов функции:

setTimeout(showmessage, 1000);

function showmessage(){
	alert('1-секундная задержка прошла');
}

JS

Также, метод setTimeout можно отменить с помощью метода clearTimeout(id).

var timeout_id = setTimeout(function(){
	alert('1-секундная задержка прошла');
}, 1000);

...

clearTimeout(timeout_id);

JS

Обновлено и опубликовано Опубликовано: 13.06.2017

Инструкция представляет шпаргалку по настройке автозапуска сценария при выполнении входа в систему Windows (login).

Настройка имеет некоторые нюансы, из-за которых, даже опытные системные администраторы не сразу могут понять причину неработоспособности сценария.

И так, запускаем консоль управления групповыми политиками и создаем новый объект GPO.

1. Разрешаем запуск скриптов.

Конфигурация компьютера Административные шаблоны Компоненты Windows Windows Powershell
(Computer Configuration  Administrative Templates  Windows Components  Windows PowerShell)

Находим параметр Включить выполнение сценариев (Turn On Script Execution) и выставляем значение Включить и в выпадающем списке Разрешить все сценарии.

2. Настраиваем время задержки для выполнения скриптов.

Конфигурация компьютера Административные шаблоны Система Групповая политика
(Computer Configuration  Administrative Templates System Group Policy)

Находим параметр Настроить задержку сценария входа в систему (Configure Logon Script Delay) и выставляем значение Включить и время задержки в минутах, например 1.

* как показала практика, лучше ставить хоть какую-то задержку.

3. Настраиваем автозапуск скрипта при входе.

Конфигурация компьютера (или Конфигурация пользователя) Политики Конфигурация Windows Сценарии
(Computer Configuration или User Configuration Policies Windows Settings Scripts)

В данной ветке мы увидим параметры для настройки сценария при входе или выходе из системы (включении или выключении компьютера). Дважды кликаем по нужному параметру и переходим на вкладку Сценарии Powershell (Powershell Scripts).

Нажимаем по Добавить и выбираем заранее написанный скрипт.

Если необходимо задать приоритет сценариям перед обычными сценариями, в выпадающем списке «Для этого объекта групповой политики выполните сценарии в следующем порядке» выбираем нужный пункт.

Дмитрий Моск — частный мастер

Была ли полезна вам эта инструкция?

Да            Нет

(PHP 4, PHP 5, PHP 7, PHP 8)

sleepЗадержка выполнения

Описание

sleep(int $seconds): int

Откладывает исполнение программы на число секунд, указанное в параметре
seconds.

Замечание:

Чтобы отложить выполнение программы на доли секунды,
используйте функцию usleep(), поскольку функция sleep()
ожидает целое число (int).
Например, sleep(0.25) приостановит выполнение программы на 0 секунд.

Список параметров

seconds

Время остановки в секундах (должно быть больше или равно 0).

Возвращаемые значения

Возвращает 0 в случае успешного выполнения.

Если вызов был прерван сигналом, функция sleep()
возвратит значение, не равное нулю. В Windows это значение всегда будет
равно 192 (значение константы Windows API
WAIT_IO_COMPLETION). На других платформах возвращаемом
значением будет количество секунд, оставшихся до задержки.

Ошибки

Если указанное число секунд в параметре seconds
отрицательное, выбрасывается исключение ValueError..

Список изменений

Версия Описание
8.0.0 Функция выбрасывает исключение ValueError,
если в параметре seconds указано отрицательное число;
ранее вместо этого выдавалась ошибка уровня E_WARNING и функция возвращала значение false.

Примеры

Пример #1 Пример использования sleep()


<?php// текущее время
echo date('h:i:s') . "n";// ожидание в течениe 10 секунд
sleep(10);// завершение ожидания
echo date('h:i:s') . "n";?>

Этот пример выведет (через 10 секунд)

Смотрите также

  • usleep() — Задержка выполнения в микросекундах
  • time_nanosleep() — Задержка на заданное число секунд и наносекунд
  • time_sleep_until() — Откладывает исполнение скрипта до заданного времени
  • set_time_limit() — Ограничение времени выполнения скрипта

ash b

8 years ago


re: "mitigating the chances of a full bruit force attack by a limit of 30 lookups a minute."

Not really - the attacker could do 100 requests. Each request might take 2 seconds but it doesn't stop the number of requests done. You need to stop processing more than one request every 2 seconds rather than delay it by 2 seconds on each execution.


Anonymous

4 years ago


Diego Andrade's msleep function is not compatible with php7's `strict_types`, cast the usleep parameter to int, and it will be,
usleep((int)($time * 1000000));

barlow at fhtsolutions dot com

11 years ago


You should put sleep into both the pass and fail branches, since an attacker can check whether the response is slow and use that as an indicator - cutting down the delay time. But a delay in both branches eliminates this possibility.

MPHH

19 years ago


Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), the sleep() function, database queries, etc. is not included when determining the maximum time that the script has been running.

Diego Andrade

7 years ago


Maybe obvious, but this my function to delay script execution using decimals for seconds (to mimic sleep(1.5) for example):

<?php
/**
* Delays execution of the script by the given time.
* @param mixed $time Time to pause script execution. Can be expressed
* as an integer or a decimal.
* @example msleep(1.5); // delay for 1.5 seconds
* @example msleep(.1); // delay for 100 milliseconds
*/
function msleep($time)
{
   
usleep($time * 1000000);
}
?>


hartmut at six dot de

22 years ago


it is a bad idea to use sleep() for delayed output effects as

1) you have to flush() output before you sleep

2) depending on your setup flush() will not work all the way to the browser as the web server might apply buffering of its own or the browser might not render output it thinks not to be complete

netscape for example will only display complete lines and will not show table parts until the </table> tag arrived

so use sleep if you have to wait  for events and don't want to burn  to much cycles, but don't use it for silly delayed output effects!


Anonymous

8 years ago


If you are having issues with sleep() and usleep() not responding as you feel they should, take a look at session_write_close()

as noted by anonymous on comments;
"If the ajax function doesn't do session_write_close(), then your outer page will appear to hang, and opening other pages in new tabs will also stall."


ealexs at gmail dot com

4 months ago


From my testing calling sleep(0); will do a `thread spin`.
It would be nice if this was to be put explicitly in the documentation as it is useful. You can do the minimum wait without overloading the CPU thread.

Anonymous

1 year ago


I wrote a simple method for sleeping with a float, which also allows you to do milliseconds (via fractional seconds).

<?php
 
function sleepFloatSecs($secs) {
   
$intSecs = intval($secs);
   
$microSecs = ($secs - $intSecs) * 1000000;

    if(

$intSecs > 0) {
     
sleep($intSecs);
    }
    if(
$microSecs > 0) {
     
usleep($microSecs);
    }
  }
?>

And testing on my machine it works perfectly:

<?php
  $x
= [0.100,0.250,0.5,1.0,1.5,2.0,2.5];

  foreach(

$x as $secs) {
   
$t = microtime(true);
   
sleepFloatSecs($secs);
   
$t = microtime(true) - $t;
    echo
"$secs t => t $tn";
  }
?>

Output:

<?php
  0.1    
=>    0.10017800331116
  0.25   
=>    0.25016593933105
  0.5    
=>    0.50015211105347
  1      
=>    1.0001430511475
  1.5    
=>    1.5003218650818
  2      
=>    2.000167131424
  2.5    
=>    2.5002470016479
?>


LVT

9 years ago


Always close your SQL connection and free the memory before using sleep( ) or you will be needlessly holding a SQL connection for [xx] seconds, remember that a shared hosting environment only allows max 30 SQL connections at the same time.

joshmeister at gmail dot com

10 years ago


Here is a simplified way to flush output to browser before completing sleep cycle.  Note the buffer must be "filled" with 4096 characters (bytes?) for ob_flush() to work before sleep() occurs.
<?php
ob_implicit_flush
(true);
$buffer = str_repeat(" ", 4096);
echo
"see this immediately.<br>";
echo
$buffer;
ob_flush();
sleep(5);
echo
"some time has passed";
?>

jimmy at powerzone dot dk

12 years ago


Notice that sleep() delays execution for the current session, not just the script. Consider the following sample, where two computers invoke the same script from a browser, which doesn't do anything but sleep.

PC 1 [started 14:00:00]: script.php?sleep=10 // Will stop after 10 secs

PC 1 [started 14:00:03]: script.php?sleep=0 // Will stop after 7 secs

PC 2 [started 14:00:05]: script.php?sleep=0 // Will stop immediately

http://php.net/session_write_close may be used to address this problem.


Anonymous

13 years ago


This will allow you to use negative values or valuer below 1 second.

<?php slaap(0.5); ?>



<?php

function slaap($seconds)

{

   
$seconds = abs($seconds);

    if (
$seconds < 1):

      
usleep($seconds*1000000);

    else:

      
sleep($seconds);

    endif;   

}

?>


manu7772 at gmail dot com

1 year ago


Sleep method with parameter in milliseconds :

public static function ms_sleep($milliseconds = 0) {
    if($milliseconds > 0) {
        $test = $milliseconds / 1000;
        $seconds = floor($test);
        $micro = round(($test - $seconds) * 1000000);
        if($seconds > 0) sleep($seconds);
        if($micro > 0) usleep($micro);
    }
}


sergio at inbep dot com dot br

6 years ago


To use float or int numbers

function pause($seconds)
{
    usleep($seconds * 1000000);
}

pause(0.25);


f dot schima at ccgmbh dot de

13 years ago


Remember that sleep() means "Let PHP time to do some other stuff".
That means that sleep() can be interrupted by signals. That is important if you work with pcntl_signal() and friends.

toddjt78 at msn dot com

12 years ago


Simple function to report the microtime since last called or the microtime since first called.

<?php

function stopWatch($total = false,$reset = true){

    global
$first_called;

    global
$last_called;

   
$now_time = microtime(true);

    if (
$last_called === null) {

       
$last_called = $now_time;

       
$first_called = $now_time;

    }

    if (
$total) {

       
$time_diff = $now_time - $first_called;

    } else {

       
$time_diff = $now_time - $last_called;

    }

    if (
$reset)

       
$last_called = $now_time;

    return
$time_diff;

}

?>



$reset  - if true, resets the last_called value to now

$total - if true, returns the time since first called otherwise returns the time since last called


code {@} ashleyhunt [dot] co [dot] uk

11 years ago


A really simple, but effective way of majorly slowing down bruit force attacks on wrong password attempts.

In my example below, if the end-user gets the password correct, they get to log in at full speed, as expected. For every incorrect password attempt, the users response is delayed by 2 seconds each time; mitigating the chances of a full bruit force attack by a limit of 30 lookups a minute.

I hope this very simple approach will help make your web applications that little bit more secure.

Ashley

<?php
public function handle_login() {
    if(
$uid = user::check_password($_REQUEST['email'], $_REQUEST['password'])) {
        return
self::authenticate_user($uid);
    }
    else {
       
// delay failed output by 2 seconds
        // to prevent bruit force attacks
       
sleep(2);
        return
self::login_failed();
    }
}
?>


LVT

9 years ago


Another reason for not to abuse sleep( ) is that along with the maximum of 30 sql connections, a shared hosting environment usually limits the number of processes to 20, if your website has many users online and you put sleep( ) everywhere in the code, your server will throw a 508 error (resource limit reached) and will stop serving your website.

soulhunter1987 at post dot ru

12 years ago


Since sleep() can be interrupted by signals i've made a function which can also be interrupted, but will continue sleeping after the signal arrived (and possibly was handled by callback). It's very useful when you write daemons and need sleep() function to work as long as you 'ordered', but have an ability to accept signals during sleeping.

<?php

function my_sleep($seconds)

{

   
$start = microtime(true);

    for (
$i = 1; $i <= $seconds; $i ++) {

        @
time_sleep_until($start + $i);

    }

}

?>


smcbride at msn dot com

1 year ago


An example of using sleep to run a set of functions at different intervals.  This is not a replacement for multi-threading, but it could help someone that wants to do something cheap.  You don't have to use eval().  It is just used as an example.  This is different than running a standard 1 second sleep loop, due to sleeping longer does not consume as much CPU.

<?php// current time
echo date('h:i:s') . "n";// Some example functions
function function_a() { echo 'function_a called @ ' . date('h:i:s') . PHP_EOL; }
function
function_b() { echo 'function_b called @ ' . date('h:i:s') . PHP_EOL; }
function
function_c() { echo 'function_c called @ ' . date('h:i:s') . PHP_EOL; }// Add some timers (in seconds) with function calls
$sleeptimers = array();
$sleeptimers['5'][0]['func'] = 'function_a();';
$sleeptimers['10'][0]['func'] = 'function_b();';
$sleeptimers['15'][0]['func'] = 'function_c();';// Process the timers
while(true) {
   
$currenttime = time();
   
reset($sleeptimers);
   
$mintime = key($sleeptimers);
    foreach(
$sleeptimers as $SleepTime => $Jobs) {
        foreach(
$Jobs as $JobIndex => $JobDetail) {
            if(!isset(
$JobDetail['lastrun'])) {
               
$sleeptimers[$SleepTime][$JobIndex]['lastrun'] = time();
                if(
$SleepTime < $mintime) $mintime = $SleepTime;
            } elseif((
$currenttime - $JobDetail['lastrun']) >= $SleepTime) {
                eval(
$JobDetail['func']);
               
$lastrun = time();
               
$sleeptimers[$SleepTime][$JobIndex]['lastrun'] = $lastrun;
               
$mysleeptime = $SleepTime - ($currenttime - $lastrun);
                if(
$mysleeptime < 0) $mysleeptime = 0;
                if((
$currenttime - $JobDetail['lastrun']) < $mintime) $mintime = $mysleeptime// account for length of time function runs
               
echo 'Sleep time for function ' . $JobDetail['func'] . ' = ' . $mysleeptime . PHP_EOL;
            }
        }
    }
    echo
'Sleeping for ' . $mintime . ' seconds' . PHP_EOL;
   
sleep($mintime);
}
?>


webseos at gmail dot com

14 years ago


This is a critical thing to use time delay function as sleep() Because a beginner can find that this is not working and he/she will see that all output appearing at a time.

A good way to implement this is by using the function -  ob_implicit_flush() then you don't need to use flush() function explicitly.

A sample code :
<?php
ob_implicit_flush
(true);
for(
$i=0;$i<5;$i++)
{
$dis=<<<DIS
<div style="width:200px; background-color:lime;border:1px; text-align:center;text-decoration:blink;">
$i
</div>
DIS;
echo
$dis;sleep(5);
//flush();
}


mohd at Bahrain dot Bz

13 years ago


I hope this code will help somebody to solve the problem of not being able to flush or output the buffer to the browser (I use IE7).
It may work for you with just [ echo str_repeat(".", 4096); ] and without even using ob_... and flush.

<?php
ob_start
();ob_implicit_flush(true);
//[ OR ] echo "..."; ob_flush(); flush();set_time_limit(0);

function

sleep_echo($secs) {
   
$secs = (int) $secs;
   
$buffer = str_repeat(".", 4096);
   
//echo $buffer."rn<br />rn";
   
for ($i=0; $i<$secs; $i++) {
        echo
date("H:i:s", time())." (".($i+1).")"."rn<br />rn".$buffer."rn<br />rn";
       
ob_flush();
       
flush();
       
sleep(1);
       
//usleep(1000000);
   
}
}
sleep_echo(30);ob_end_flush();
?>


Многие языки программирования имеют функцию сна, которая будет задерживать выполнение программы на несколько секунд. Однако эта функциональность отсутствует в JavaScript из-за ее асинхронного характера.

В этой статье, мы кратко рассмотрим почему так может быть, а затем как мы можем реализовать функцию сна самостоятельно.

Понимания модели исполнения JavaScript

Перед тем, как мы приступим, важно убедится, что мы правильно понимаем модель выполнения JavaScript.

Рассмотрим следующий код Ruby:

require 'net/http'
require 'json'

url = 'https://api.github.com/users/jameshibbard'
uri = URI(url)
response = JSON.parse(Net::HTTP.get(uri))
puts response['public_repos']
puts "Hello!"

Как и следовало ожидать, этот код отправляет запрос к GitHub API для получения моих пользовательских данных. Затем он анализирует ответ, выводит количество открытых репозиториев, относящихся к моей учетной записи GitHub, и, наконец, выводит на экран «Hello!». Исполнение идет сверху вниз.

Сравните его с эквивалентной версией в JavaScript:

fetch('https://api.github.com/users/jameshibbard')           .then(res => res.json())         
   .then(json => console.log(json.public_repos)); 
console.log("Hello!");

Если вы запустите этот код, он выведет «Hello!» На экран, а затем количество публичных репозитеров, связанных с моей учетной записью GitHub.

Это связано с тем, что выборка данных из API является асинхронной операцией в JavaScript. Интерпретатор JavaScript встретит команду fetch и отправит запрос. Однако, он не будет ждать завершения запроса. Скорее всего, он продолжит свой путь, выведет «Hello!» на консоль, а затем, когда запрос вернется через пару сотен миллисекунд, выдаст количество репозитеров.

Возможно, Вам не нужна функция сна

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

Создание простой задержки, используя setTimeout

Стандартный способ создания задержки в JavaScript это использовать метод setTimeout. Например:

console.log("Hello"); 
setTimeout(() => {  console.log("World!"); }, 2000);

Он будет показывать «Hello!» на консоли, а затем через две секунд «World!». И во многих случаях этого достаточно: сделать что-то, подождать, затем сделать что-то еще. Выполнено!

Однако, имейте ввиду, что метод setTimeout асинхронный. Попробуйте изменить предыдущий код следующим образом:

console.log("Hello"); 
setTimeout(() => { console.log("World!"); }, 2000); 
console.log("Goodbye!");

Оно покажет это:

Hello 
Goodbye! 
World!

В ожидании вещей с setTimeout

Также возможно использовать setTimeout (или его двоюродного брата setInterval), чтобы заставить JavaScript ждать пока не будет выполнено условие. Например, вот как вы можете использовать setTimeout, чтобы дождаться появления определенного элемента на веб-странице:

function pollDOM () { 
  const el = document.querySelector('my-element'); 

  if (el.length) {                  
    // Do something with el          
  } else {                 
    setTimeout(pollDOM, 300); // try again in 300 milliseconds        
  } 
}  

pollDOM();

Это предполагает, что элемент появится в какой-то момент. Если вы не уверены, что это так, вам нужно посмотреть на отмену таймера (используя clearTimeout или clearInterval).

Управление потоком в современном JavaScript

При написании JavaScript часто бывает необходимо подождать, пока что-то произойдет (например, данные должны быть получены из API), а затем сделать что-то в ответ (например, обновить пользовательский интерфейс для отображения данных).

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

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

Например, используя асинхронное ожидание, мы можем переписать исходный код, чтобы получить информацию из GitHub API:

(async () => {       
  const res = await fetch(`https://api.github.com/users/jameshibbard`);        
  const json = await res.json();        
  console.log(json.public_repos);         
  console.log("Hello!"); 
})();

Теперь код будет выполнятся с верху вниз. Интерпретатор JavaScript ожидает завершение сетевого запроса, и сначала регистрирует количество открытых репозитеров, а затем сообщение «Hello!».

Сон в изначальном JavaScript

Если вы все еще читаете, вы вполне готовы заблокировать поток выполнения и заставить JavaScript ждать его.

Вот как вы можете это сделать:

function sleep(milliseconds) {       
    const date = Date.now();        
    let currentDate = null;       
    do {               
       currentDate = Date.now();      
    } while (currentDate - date < milliseconds); 
}  

console.log("Hello"); 
sleep(2000); 
console.log("World!");

Как и ожидалось, сначала отобразится «Hello», затем будет пауза в две секунды, затем отобразится «World!»

Он работает с помощью метода Date.now, чтобы получить количество миллисекунд, прошедших с 1 января 1970 года, и присвоить это значение переменной дате. После он создает пустую переменную currentDate перед входом в цикл do … while. В цикле он многократно получает количество миллисекунд, прошедших 1 января 1970 года, и присваивает значение ранее объявленной переменной currentDate. Цикл будет продолжаться, пока разница между date и currentDate будет меньше желаемой задержки в миллисекунд.

Работа выполнена, не так ли? Ну, не совсем…

Лучшая функция сна

Может этот код делает в точности то, на что Вы надеялись он будет делать, но имейте ввиду, у него есть большой недостаток: цикл будет блокировать поток выполнения JavaScript и гарантировать, что никто не сможет взаимодействовать с вашей программой до ее завершения. Если вам нужна большая задержка, есть вероятность, что это может даже привести к поломке.

Так что делать?

Ну, также возможно объединить методы, изученные ранее в статье, чтобы сделать менее навязчивую функцию сна:

function sleep(ms) {        
   return new Promise(resolve => setTimeout(resolve, ms)); }  

console.log("Hello"); 
sleep(2000).then(() => { console.log("World!"); });

Этот код будет отображать «Hello!», затем пауза на две секунды, затем отобразит «World!». Незримо для окружающих, мы используем метод setTimeout, для разрешения Promise через заданное количество миллисекунд.

Обратите внимание, что нам нужно использовать обратный вызов then, чтобы убедится, что второе сообщение записывается задержкой. Мы также можем связать больше обратных вызовов на первый:

console.log("Hello"); 
sleep(2000)      
     .then(() => { console.log("World!"); })      
     .then(() => {           
         sleep(2000)                   
             .then(() => { console.log("Goodbye!"); })             });

Это работает, но выглядит некрасиво. Мы можем сделать это с помощью async … await:

function sleep(ms) {         
  return new Promise(resolve => setTimeout(resolve, ms)); }  

async function delayedGreeting() {        
  console.log("Hello");         
  await sleep(2000);         
  console.log("World!");         
  await sleep(2000);        
  console.log("Goodbye!"); 
} 

delayedGreeting();

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

Конечно, оба этих метода по-прежнему имеют недостаток (или особенность) в том, что они не приостанавливают выполнение всей программы. Спит только Ваша функция:

function sleep(ms) {        
   return new Promise(resolve => setTimeout(resolve, ms)); }  

async function delayedGreeting() {        
   console.log("Hello");        
   await sleep(2000);       
   console.log("World!"); 
}  

delayedGreeting(); 
console.log("Goodbye!");

Код выше регистрирует следующее:

Hello 
Goodbye! 
World!

Вывод

Проблемы синхронизации в JavaScript являются причиной головных болей для многих разработчиков, и то, как Вы справляетесь с ними, зависит от того, чего Вы пытаетесь достичь.

Хотя функция сна присутствует во многих других языках, я рекомендую вам принять асинхронную природу JavaScript и стараться не бороться с языком. Это на самом деле, довольно приятно, когда Вы привыкните к этому.

Понравилось то, что вы прочитали?

Подписывайтесь на нашу рассылку и получайте ежедневные обновления о новых учебниках, статьях, курсах и о многом другом! 

Просто введите ваш адрес электронной почты, чтобы подписаться.

(Без спамов; ежемесячно два письма; отписаться от рассылки можно в любое время)

.

Во многих языках программирования есть функция sleep, которая может задерживать
выполнение программы на несколько секунд. Но в JavaScript такая функция отсутствует из-за его асинхронного
характера. В этой статье мы рассмотрим как реализовать js sleep самостоятельно.

js sleep

setTimout и sleep в JavaScript

Для того, чтобы лучше понять проблему, посмотрите следующий код. Он делает запрос к API GitHub для получения
пользовательских данных, затем выводит количество публичных репозиториев и, наконец, пошлет в консоль «Привет!»


JS
fetch('https://api.github.com/users/username')
  .then(res => res.json())
  .then(json => console.log(json.public_repos));
console.log("Привет!");

Но если запустить такой код, то сначала он выведет на экран «Привет!», а уже потом количество публичных
репозиториев.

Так происходит, потому что получение данных от API — это асинхронная операция в JavaScript. Интерпритатор
JavaScript встретит команду fetch и отправит запрос. Он не будет ждать завершения
запроса и выведет «Привет!» в консоль, и потом через пару сотен миллисекунд выдаст количество рекозиториев.

Создаем простую задержку с помощью js setTimeout

Теперь, давайте рассмотрим создание задержки в JavaScript, используя метод setTimeout.


JS
console.log("Привет");
setTimeout(() => { console.log("мир"); }, 3000);

Этот код запишет в консоль «Привет», а затем через 3 секунды «мир» ‐ во многих случаях такой задержки
достаточно. Но имейте ввиду, что в js setTimeout ‐ это асинхронный метод. Попробуйте
изменить предыдущий код следующим образом:


JS
console.log("Привет");
setTimeout(() => { console.log("мир"); }, 3000);
console.log("Пока");

Этот код выведет: Привет Пока мир.

Вы также можете использовать setTimeout (или его брата setInterval),
чтобы заставить JavaScript подождать пока не будет выполнено какое-либо условие. К примеру, вам нужно дождаться
появления определенного элемента на странице:


JS
function waitForDOM () {
  const container = document.querySelector('container');

  if (container.length) {
    // Делаем что-то с контейнером
  } else {
    setTimeout(waitForDOM, 300); // Попробовать снова через 300 миллисекунд
  }
}

waitForDOM();

Управление потоком в современном JavaScript

В JavaScript часто бывают ситуации, когда вам нужно подождать, пока то-то произойдет, а затем сделать что-то в
ответ. В примере выше мы использовали анонимную callback функцию. Но что если вам нужно подождать несколько событий?
В этом случае синтаксис быстро становится довольно грубым.

К счастью, язык значительно изменился за последние несколько лет и теперь у нас есть новые конструкции для этих
целей. К примеру, мы может переписать код для получения информации из API GitHub, используя async await.


JS
(async () => {
  const res = await fetch(`https://api.github.com/users/username`);
  const json = await res.json();
  console.log(json.public_repos);
  console.log("Привет!");
})();

Теперь код выполняется сверху вниз.

Sleep в JavaScript

Мы уже готовы остановить поток выполнения программы и заставить JavaScript спать. Вот как мы можем это сделать:


JS
function sleep(milliseconds) {
  const date = Date.now();
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

console.log("Привет");
sleep(2000);
console.log("мир");

В результате сначала в консоли отобразится «Привет», пауза на две секунды, а затем «мир». Функция работает с помощью
метода Date.now, получает количество миллисекунд, прошедших с 1 января 1970
года, и присваивает это значение переменной date. Запускает цикл, который будет
продолжаться, пока разница
между date и currentDate будет меньше нужной задержки.

Улучшаем функцию js sleep

Функция делает то, что нам нужно, но у нее есть недостаток: если вам нужна большая задержка, то она может привести к
поломке программы. Объединим методы изученные ранее в статье, чтобы сделать менее навязчивую функцию сна.


JS
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

console.log("Привет");
sleep(2000).then(() => { console.log("мир"); });

Этот код выведет в консоль «Привет», подождет 2 секунды, затем выведет «мир». Внутри мы используем Promise.

Сделаем JavaScript функцию sleep с помощью async … await:


JS
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedGreeting() {
  console.log("Привет");
  await sleep(2000);
  console.log("мир");
}

delayedGreeting();
console.log("Пока");

Материал из Справочник Web-языков

Перейти к: навигация, поиск

Содержание

  • 1 set_time_limit
  • 2 sleep
  • 3 usleep
  • 4 die
  • 5 exit
  • 6 assert
  • 7 assert_options
  • 8 eval

set_time_limit

Установка предельного времени исполнения сценария.

Синтаксис:

void set_time_limit(int seconds)

При запуске сценария PHP запускает системный таймер, и если время (выделенное сценарию для выполнения) истекает, а сценарий еще не завершился, PHP принудительно завершает сценарий (генерируя фатальную ошибку исполнения). Это не допускает скопления большого количества сценариев, расходующих ресурсы сервера, но, повидимому, «зависших» (например, если в них обнаружился бесконечный цикл или они пытаются дождаться подключения к не отвечающему серверу).

По умолчанию допустимое время исполнения сценария устанавливается в файле конфигурации параметром max_execution_time (обычно оно равно 30 с). Но для текущего сценария это время можно изменить вызовом данной функции, указав время в секундах в ее аргументе. Если указывается значение 0, то тогда временное ограничение снимается.

Отсчет времени начинается от момента вызова функции. Например, если сценарий уже выполнялся в течении 15 секунд, а затем вызывается функция set_time_limit(20), то общее максимальное время исполнения сценария становится равным 35 секундам.

Если сценарий выполняется в безопасном режиме (с установленным параметром safe mode), то тогда вызов этой функции игнорируется и используется значение из файла конфигурации.

sleep

Задержка выполнения сценария.

Синтаксис:

void sleep(int seconds);

Фукция sleep() выполняет задержку выполнения сценария в секундах (seconds).

usleep

Задержка выполнения сценария в микросекундах.

Синтаксис:

void usleep(int micro_seconds);

Задержка выполнения сценария в микросекундах (micro_seconds).

Эта функция не работает в Windows.

die

Вывод сообщения и завершение текущего сценария.

Синтаксис:

void die(string message);

Эта функция выводит сообщение и прекращает выполнение текущего скрипта. Не возвращает значение.

<?php
$filename = '/path/to/data-file';
$file = fopen($filename, 'r')
 or die "unable to open file ($filename)";
?>

exit

Завершает текущий сценарий.

Синтаксис:

void exit(void);

Эта функция завершает текущий сценарий. Не возвращает значение.

assert

Проверка истинности значения.

Синтаксис:

int assert(string|bool assertion);

В качестве аргумента функции может быть указано значение или строка, содержащая код PHP (как в функции eval()). Функция проверяет, является ли значение (или выражение) равным false, и, если это так, выполняет определенные действия.

Поведение функции определяется установками в файле конфигурации или при вызове функции assert_options().

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

В целом же выполнение сценария не должно зависеть от таких проверок, а использовать обычные проверки возвращаемых функциями значений.

<?php
function handler() {
  echo "n* Failed * n";
}

assert("$a='1';");
echo "a: $a n";
assert(0);
// завершать сценарий
echo assert_options(ASSERT_BAIL, 1);
// вызвать обработчик
assert_options(ASSERT_CALLBACK, "handler");
// не выдавать сообщений PHP
@assert(--$a);
// эта строка не будет выполнена
echo "n ... n";
?>

Приведенный пример выведет:

a: 1
Warning: Assertion failed in file.php on line 20
0
* Failed *

assert_options

Определение параметров assert.

Синтаксис:

mixed assert_options(int parameter [, mixed value])

Эта функция позволяет определить поведение конструкции assert().

Возвращается предыдущее значение параметра (или значение false при ошибке), указанного в первом аргументе одной из следующих констант:

Параметр ini-параметр Умолчание Описание
ASSERT_ACTIVE asser.active 1 Разрешить указание кода в assert().
ASSERT_WARNING assert.warning 1 Выдавать предупреждение PHP.
ASSERT_BAIL assert.bail 0 Завершать выполнение, если «неистинно».
ASSERT_QUIET_EVAL assert.quiet_eval 0 Не выдавать сообщений.
ASSERT_CALLBACK assert_callback (null) Установить функцию в качестве обработчика «неистинных» assert().

Если значение необходимо переопределить, его указывают во втором аргументе.

eval

Производит выполнение строки содержащей PHP код.

Синтаксис:

void eval(string code_str);

Функция eval() производит выполнение строки, заданной в code_str содержащей PHP код. Кстати, это может пригодиться для сохранения кода в текстовом поле базы данных для более позднего выполнения. Не забывайте, что указанный в строке код должен быть синтаксически правильным (например, должны присутствовать точки с запятой после каждой команды и т.п.), в противном случае сценарий будет завершен в этой строке с ошибкой. Учитывайте также, что те значения переменных, которые будут установлены в данной строке, будут использоваться в оставшейся части сценария.

При изменении переменных значений в eval() эти переменные будут изменены и в основных данных.

Если в строке указан оператор return, то тогда выполнение указанного кода будет досрочно завершено и возвращенное значение можно будет получить как значение, возвращаемое самой функции.

<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.
';
echo $str;
eval( "$str = "$str";" );
echo $str;
?>

Результатом выполнения этого кода будет:

This is a $string with my $name in it.
This is a cup with my coffee in it.

Понравилась статья? Поделить с друзьями:
  • Задачи праздника пасха
  • Задачи праздника дня победы
  • Задачи праздника дня отца
  • Задачи праздника день села
  • Задачи праздника день победы