Чтение онлайн

ЖАНРЫ

Основы программирования на JavaScript

Кан Марк

Шрифт:

'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'];

for(var i=0; i<activeXObjects.length; i++){

try{

return new ActiveXObject(activeXObjects[i]);

}catch(err){}

}

Заранее неизвестно, какие объекты установил пользователь, и, к сожалению, браузер не предоставляет никакого механизма это определить. Поэтому остается создавать каждый из 6 возможных объектов, пока один из них (будем надеяться) не заработает.

Операторы Try/Catch можно использовать для перехвата ошибок двух типов: ошибок времени выполнения и ошибок пользователя. Ошибки времени выполнения, как говорилось ранее, возникают, когда у компилятора JavaScript существует проблема с созданным кодом. Ошибки пользователя, с другой стороны, будут технически

проходить без проблем, но возникают в связи с контекстом приложения. Если имеется поле, в которое пользователь, например, должен ввести свой возраст, и пользователь вводит – 2, то это приводит к появлению ошибки.

Блок Try/Catch имеет достаточно простой синтаксис:

try{

// код

}catch(err){

// код обработки ошибки

}

Если код в блоке try приводит к ошибке, то сценарий немедленно переходит в блок catch. Объект ошибки err в JavaScript имеет ряд полезных свойств - описание, сообщение, имя и номер, которые можно использовать для вывода информации о том, что произошло:

try{

var x;

x[5] = 5;

}catch(err){

alert('An error occured: '+err.description);

}

Если в операторе catch окажется ошибка, то JavaScript сможет обратиться в дальнейшем к ее описанию.

Такой блок кода Try/Catch можно применять в любом месте. Однако, обычно, код должен быть написан таким образом, чтобы это не нужно было использовать, - в частности, весь ввод должен проверяться.

Блок Try/Catch можно применять также для создания своих собственных ошибок:

function setAge(x){

if(typeof(x)=='undefined') throw('Вы должны ввести возраст');

if(typeof(x)!='number') throw('Возраст должен быть числом');

if(x<0) throw('Возраст не может быть меньше 0');

if(x>120) throw('Возраст не может быть больше 120');

var myAge = x;

// еще код

}

try{

setAge(userInput);

}catch(err){

alert(err);

}

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

Блок try/catch имеет еще одну часть, оператор finally:

try{

// код

}catch(err){

// код

}finally{

// код

}

Код в "завершающем блоке" будет выполняться независимо от того, что происходит с операторами Try/Catch. В чем же разница между завершающим блоком и простым размещением кода после блока try/catch? В большинстве случаев никакой разницы не будет. Однако, если блок try/catch находится в функции и происходит выход из функции в блоке try или catch, то возникнет существенное различие:

function myFunction{

try{

return someValue;

}catch(err){

return defaultValue;

}finally{

alert('finally!');

}

alert('End!');

}

В этом случае оба блока try и catch возвращают значение. Мы получим сообщение "finally!", но не получим сообщение "End!", потому что произойдет выход из функции до сообщения alert('End!'). То же самое остается справедливым для операторов Try/Catch, которые осуществляют выход из тела цикла for или while, например:

for(var i=0; i<10; i++){

try{

if(i==5) continue;

}catch(err){

//

обработка ошибки

}finally{

// код

}

// еще код

}

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

function processingFunction{

if(oXml.readyState!=4) return; // запрос не выполнен

switch(oXml.status){

case 0: case 200: // запрос выполнен

break;

case 408: case 504: // запрос превысил время ожидания

// код

break;

default: // ошибка запроса

// код

return; // возможно, вы захотите выйти

break;

}

// продолжение обработки запроса

}

oXml в этом примере является объектом XMLHttp, а функция processingFunction была присоединена к свойству onreadystatechange этого объекта.

Проверяя код статуса, мы узнаем, был ли запрос обработан успешно. Код 200 является в HTTP стандартным кодом статуса "Все прошло нормально" . Код 0 возникает при загрузке файлов из локальной файловой системы (если для этого есть соответствующие полномочия). Статус код 0 часто возникает при локальном тестировании приложения.

Коды статуса 408 и 504 представляют ситуацию с превышением времени ожидания. Очень часто это указывает на сетевые проблемы, и простое повторение запроса может разрешить проблему. Однако отметим, что эти коды представляют также слишком длительную работу сервера над ответом. Например, если существует ошибка сценария на сервере, которая приводит к бесконечному циклу, то может возникнуть код ошибки 408 или 504. В этом случае повторная попытка будет вредоносной, поэтому надо быть осторожным. Самым безопасным является уведомление пользователя и выход из функции, но это не очень корректно по отношению к пользователю.

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

Это почти все об обработке ошибок в JavaScript. Имеет смысл включать в функции обработку ошибок, но, возможно, что это не требуется для каждой функции или каждого фрагмента кода. В большинстве ситуаций достаточно проверки ввода пользователей. Для реализации проверки пользователя наиболее полезным средством является использование блоков Try/Catch/Throw.

В следующей лекции будет рассмотрена рекурсия:

"Чтобы понять рекурсию, сначала необходимо понять рекурсию".

Лекция 12. Рекурсия

Рекурсия. Стек. Создание собственного стека. Применение рекурсии.
"Чтобы понять рекурсию, сначала необходимо понять рекурсию".

Данное высказывание очень четко выражает суть рекурсии. Рекурсия является базовой концепцией программирования вообще, а не только JavaScript, понимание которой очень полезно. Она включает вызов функции из той же самой функции. Почему это может понадобиться? Предположим, что имеется массив массивов. Каждый из этих массивов может иметь в себе массивы, которые могут иметь массивы, которые могут иметь ... собственно, в этом и состоит идея. Таким образом мы имеем множество массивов в других массивах. Как выполнить одну и ту же операцию на всех элементах во всех этих массивах? Можно попробовать использовать простой цикл for, но неизвестно, сколько имеется массивов, и неизвестно, как глубоко распространяется вложение массивов. Поэтому остается только концепция рекурсии.

Поделиться с друзьями: