php - попробуйте, поймайте и повторите попытку

23

Иногда мой код ломается, и он находится вне моего контроля

Как я могу сделать следующее?

try {
//do my stuff
}
catch {
//sleep and try again
}

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

    
задан user3869692 28.07.2014 в 20:47
источник
  • Сделайте это в цикле. –  deceze♦ 28.07.2014 в 20:48
  • Как это будет выглядеть? –  user3869692 28.07.2014 в 21:01
  • Сколько раз вы хотите повторить одну и ту же операцию? Почему вы хотите повторить операцию, которая не работает? Что именно вне вашего контроля? –  oliakaoil 28.07.2014 в 21:06
  • Пара раз. Я использую сторонний api, который время от времени падает на пару минут. –  user3869692 28.07.2014 в 21:10

4 ответа

35

Вы можете попробовать что-то вроде этого:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

$NUM_OF_ATTEMPTS = 5;
$attempts = 0;

do {

    try
    {
        executeCode();
    } catch (Exception $e) {
        $attempts++;
        sleep(1);
        continue;
    }

    break;

} while($attempts < $NUM_OF_ATTEMPTS);

function executeCode(){
    echo "Hello world!";
}

Здесь мы выполняем цикл do...while , чтобы код выполнялся хотя бы один раз. Если функция executeCode() обнаруживает ошибку, она выдает Exception , которое будет захвачен блок try...catch . Блок catch затем увеличит переменную $attempt на единицу и вызовет continue , чтобы проверить условие while для следующей итерации. Если уже было пять попыток, цикл завершится, и скрипт может продолжить работу. Если ошибки нет, т. Е. Оператор continue из блока catch не будет выполнен, цикл будет break , тем самым завершив скрипт.

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

Если вы считаете, что ваш код может терпеть неудачу много раз, функция sleep() может быть полезна до оператора continue . «Замедление» по бесконечному циклу поможет с уменьшением CPU Usage .

Не рекомендуется запускать сценарий бесконечно до тех пор, пока он не будет успешным, поскольку ошибка, которая присутствует в первых 100 итерациях цикла, вряд ли когда-либо будет разрешена, что заставило сценарий «заморозить», вверх. Больше, чем нет, лучше переоценить код, который вы бы хотели запускать несколько раз в случае ошибки, и улучшить его, чтобы должным образом обрабатывать любые возникающие ошибки.

    
ответ дан noahnu 28.07.2014 в 21:26
  • Это временно, поэтому я буду использовать это, пока не найду решение. Я немного отредактировал его для использования. благодаря –  user3869692 28.07.2014 в 21:48
  • mm ... интересно ... –  Emiliano 28.10.2016 в 17:23
  • Отличный пример (лучший в этом потоке), но я не думаю, что вызов set_error_handler () абсолютно необходим, если вы специально не захотите поймать каждое уведомление PHP, предупреждение и синтаксическую ошибку в дополнение к обычным исключениям. Регулярный try / catch будет по-прежнему захватывать исключения, исходящие из внутренних функций PHP, а также те, которые вы бросаете сами. –  Simon East 15.05.2017 в 00:01
  • Отличный пример (лучший в этом потоке), но я не думаю, что вызов set_error_handler () абсолютно необходим, если вы специально не захотите поймать каждое уведомление PHP, предупреждение и синтаксическую ошибку в дополнение к обычным исключениям. Регулярный try / catch будет по-прежнему захватывать исключения, исходящие из внутренних функций PHP, а также те, которые вы бросаете сами. –  Simon East 15.05.2017 в 00:01
0

Просто:

function doSomething($params, $try = 1){
    try{
        //do something
        return true;
    }
    catch(Exception $e){
        if($try <5)
             sleep(10);
             //optionnaly log or send notice mail with $e and $try
             doSomething($params, $try++);
        else 
             return false;
    }
}
    
ответ дан Reign.85 23.05.2018 в 11:41
0

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

while(true){
    // execute the code you are attempting
    if(some condition to signal success){
        break; // exit the loop
    }

    sleep(2); // 2 seconds
}
    
ответ дан Alex 28.07.2014 в 21:19
  • Повторная попытка после сна (но обычно с максимальным количеством попыток избежать бесконечных циклов) очень часто встречается при работе с внешними службами, которые могут быть недоступны –  Nazareno Lorenzo 18.08.2015 в 20:29
  • Это просто повторное условие. Я думаю, что основной запрос заключается в том, как повторить попытку? Проверка только определенного условия, безусловно, далека от того, что пытается поймать, что предотвращает все исключения. –  cytsunny 26.03.2018 в 05:49
-1

Чтобы уловить исключение, вы должны сначала выбросить его. Что-то вроде этого.

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo "Hello World\n";
?>

Есть определенные встроенные исключения: Ссылка

    
ответ дан Varun Nath 28.07.2014 в 20:53