Какой оператор используется для выброса исключений javascript. Try… catch VS if…else

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

Ошибки бывают в основном 2-х типов — это синтаксические и логические. К синтаксическим можно отнести ошибки в имени переменных, функций, ошибки в синтаксисе кода. В принципе такие ошибки легко отловить через консоль браузера.

А вот логические ошибки с ними все не так просто потому, что они приводят к неправильному выполнению кода программы. Поэтому для их устранения потребуется отладка программы, чтобы понять что собственно происходит на каждом шаге скрипта. Мы же с вами здесь рассмотрим в основном локализацию синтаксических ошибок с помощью конструкции try…catch.



Конструкция перехвата ошибок try…catch

Конструкция try..catch состит из 2-х блоков: try, и затем catch. Вот пример записи в общем виде

Try { // код... } catch (err) { // обработка ошибки }

Работает эта конструкция таким образом:

  • Выполняется код внутри блока try, так называемой ловушки.
  • Если в нём не встречаются ошибки, то блок catch(err) игнорируется.
  • А вот, если в нём возникнет ошибка, то выполнение try будет прервано на ошибке, и управление передается в начало блока catch(err). При этом переменная err (можно выбрать любое другое название) будет содержать объект ошибки с подробнейшей информацией о произошедшей ошибке.
  • Поэтому при ошибке в try скрипт не останавливается, и даже более того мы имеем возможность обработать ошибку внутри блока catch.

    Рассмотрим это на примерах.

    • Пример без ошибок: при запуске сработают alert (1) и (2): try { alert("Блок try"); // (1) getMessage(); //выведет либо сообщение об ошибке подключения, либо об ошибке выбора
      }

      И в зависимости от результата мы бы:

      * удачно присоединились бы к СУБД и выбрали БД (код в сatch блоке не выполнился бы)
      * при неудаче соединения с СУБД, вывели бы соответствующую ошибку и прикатили выполнение сеанса
      * при ошибке выбора БД, оповестили бы пользователя об этой неприятности

      Теперь самое время спросить: \\\«А зачем нам такая сложная штука, если можно использовать оператор if?\\\».

      Первый же ответ: \\\«Потому что так код более читабельный, а обработка ошибок выведена в отдельный блок\\\». Если бы мы использовали оператор if, то код выглядел бы следующим образом:

      $connId = mysql_connect($hostname, $username, $password);
      if (false == $connId) {
      echo \\\"Ошибка подключения к СУБД\\\";
      }

      $flag = mysql_select_db($dbname);
      if (false == $flag) {
      echo \\\"Невозможно выбрать базу данных.\\\";
      }

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

      class MyException extends Exception {}

      Try {
      try {
      //...
      throw new Exception(\\\"inner\\\");
      //...
      } catch (Exception $e) {
      throw new MyException(\\\"outer\\\");
      }
      } catch (MyException $e) {
      echo $e->getMessage(); //выведет \\\"outer\\\"
      }

      Производительность Пытаясь достичь истины, провел несколько экспериментов с различными типами функций.
      Первый тип возвращал статус true и проверялся операторами if...else
      Второй тип возвращал статус false и проверялся операторами if...else
      Третий тип просто выполнял действия и ничего не возвращал. Проверялся блоком try...catch
      Четвертый тип всегда бросал исключение и проверялся в try...catch

      Результаты:

      True: 0.72382092475891
      False: 0.85190796852112
      No exception: 0.72565317153931
      Exception: 14.176206827164

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

      ВыводыКогда же использовать исключения? Всегда, когда подразумевается ошибка или нестандартное поведение программы, а так же когда принятие решения об обработке результата необходимо переложить на более высокий уровень.
      А что же делать с оператором if и булевыми статусами отработки функций? Оставить их. Но толко там где они действительно необходимы. Тоесть там, где логический оператор подразумевает использование результата в вычислениях, а не контроле потока выполнения. Тоесть все удачные завершения функций теперь не нужно оповещать оператором return true, если это логическое значение не пригодиться для дальнейших вычислений. И в то же время все статусы завершения функций с ошибками изменить из формата return false в формат throw new Exception()
      Что нужно помнить? Использование исключений предполагает что весь код выполняется со статусом true (без ошибок), но если ошибка произошла, то для ее обработки всегда найдется место в блоке catch.