Ðак Ð±Ñ Ð¼Ñ Ñ Ð¾ÑоÑо ни пÑогÑаммиÑовали, в коде бÑваÑÑ Ð¾Ñибки. Ðли, как Ð¸Ñ Ð¸Ð½Ð°Ñе назÑваÑÑ, «иÑклÑÑиÑелÑнÑе ÑиÑÑаÑии» (иÑклÑÑениÑ).
ÐбÑÑно ÑкÑÐ¸Ð¿Ñ Ð¿Ñи оÑибке, как говоÑÑÑ, «падаеÑ», Ñ Ð²Ñводом оÑибки в конÑолÑ.
Ðо бÑваÑÑ ÑлÑÑаи, когда нам Ñ Ð¾ÑелоÑÑ Ð±Ñ ÐºÐ°Ðº-Ñо конÑÑолиÑоваÑÑ ÑиÑÑаÑиÑ, ÑÑÐ¾Ð±Ñ ÑкÑÐ¸Ð¿Ñ Ð½Ðµ пÑоÑÑо «Ñпал», а Ñделал ÑÑо-Ñо ÑазÑмное.
ÐÐ»Ñ ÑÑого в JavaScript еÑÑÑ Ð·Ð°Ð¼ÐµÑаÑелÑÐ½Ð°Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ try..catch.
ÐонÑÑÑÑкÑÐ¸Ñ tryâ¦catch
ÐонÑÑÑÑкÑÐ¸Ñ try..catch ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· двÑÑ
оÑновнÑÑ
блоков: try, и заÑем catch:
try {
// код ...
} catch (err) {
// обÑабоÑка оÑибки
}
РабоÑÐ°ÐµÑ Ð¾Ð½Ð° Ñак:
-
ÐÑполнÑеÑÑÑ ÐºÐ¾Ð´ внÑÑÑи блока
try. -
ÐÑли в нÑм оÑибок неÑ, Ñо блок
catch(err)игноÑиÑÑеÑÑÑ, Ñо еÑÑÑ Ð²Ñполнение Ð´Ð¾Ñ Ð¾Ð´Ð¸Ñ Ð´Ð¾ конÑаtryи поÑом пÑÑÐ³Ð°ÐµÑ ÑеÑезcatch. -
ÐÑли в нÑм Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ Ð¾Ñибка, Ñо вÑполнение
tryна ней пÑеÑÑваеÑÑÑ, и ÑпÑавление пÑÑÐ³Ð°ÐµÑ Ð² наÑало блокаcatch(err).ÐÑи ÑÑом пеÑеменнаÑ
err(можно вÑбÑаÑÑ Ð¸ дÑÑгое название) бÑÐ´ÐµÑ ÑодеÑжаÑÑ Ð¾Ð±ÑÐµÐºÑ Ð¾Ñибки Ñ Ð¿Ð¾Ð´Ñобной инÑоÑмаÑией о пÑоизоÑедÑем.
Таким обÑазом, пÑи оÑибке в try ÑкÑÐ¸Ð¿Ñ Ð½Ðµ «падаеÑ», и Ð¼Ñ Ð¿Ð¾Ð»ÑÑаем возможноÑÑÑ Ð¾Ð±ÑабоÑаÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð²Ð½ÑÑÑи catch.
ÐоÑмоÑÑим ÑÑо на пÑимеÑÐ°Ñ .
-
ÐÑÐ¸Ð¼ÐµÑ Ð±ÐµÐ· оÑибок: пÑи запÑÑке ÑÑабоÑаÑÑ
alert(1)и(2):try { alert('ÐаÑало блока try'); // (1) <-- // .. код без оÑибок alert('ÐÐ¾Ð½ÐµÑ Ð±Ð»Ð¾ÐºÐ° try'); // (2) <-- } catch(e) { alert('Ðлок catch не полÑÑÐ¸Ñ ÑпÑавление, Ñак как Ð½ÐµÑ Ð¾Ñибок'); // (3) } alert("ÐоÑом код пÑÐ¾Ð´Ð¾Ð»Ð¶Ð¸Ñ Ð²Ñполнение..."); -
ÐÑÐ¸Ð¼ÐµÑ Ñ Ð¾Ñибкой: пÑи запÑÑке ÑÑабоÑаÑÑ
(1)и(3):try { alert('ÐаÑало блока try'); // (1) <-- lalala; // оÑибка, пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð½Ðµ опÑеделена! alert('ÐÐ¾Ð½ÐµÑ Ð±Ð»Ð¾ÐºÐ° try'); // (2) } catch(e) { alert('ÐÑибка ' + e.name + ":" + e.message + "\n" + e.stack); // (3) <-- } alert("ÐоÑом код пÑÐ¾Ð´Ð¾Ð»Ð¶Ð¸Ñ Ð²Ñполнение...");
try..catch подÑазÑмеваеÑ, ÑÑо код ÑинÑакÑиÑеÑки веÑенÐÑли гÑÑбо наÑÑÑена ÑÑÑÑкÑÑÑа кода, напÑÐ¸Ð¼ÐµÑ Ð½Ðµ закÑÑÑа ÑигÑÑÐ½Ð°Ñ Ñкобка или где-Ñо ÑÑÐ¾Ð¸Ñ Ð»Ð¸ÑнÑÑ Ð·Ð°Ð¿ÑÑаÑ, Ñо никакой try..catch здеÑÑ Ð½Ðµ поможеÑ. Такие оÑибки назÑваÑÑÑÑ ÑинÑакÑиÑеÑкими, инÑеÑпÑеÑаÑÐ¾Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð½ÑÑÑ Ñакой код.
ÐдеÑÑ Ð¶Ðµ Ð¼Ñ ÑаÑÑмаÑÑиваем оÑибки ÑеманÑиÑеÑкие, Ñо еÑÑÑ Ð¿ÑоиÑÑ Ð¾Ð´ÑÑие в коÑÑекÑном коде, в пÑоÑеÑÑе вÑполнениÑ.
try..catch ÑабоÑÐ°ÐµÑ ÑолÑко в ÑинÑ
Ñонном кодеÐÑибкÑ, коÑоÑÐ°Ñ Ð¿ÑоизойдÑÑ Ð² коде, запланиÑованном «на бÑдÑÑее», напÑÐ¸Ð¼ÐµÑ Ð² setTimeout, try..catch не поймаеÑ:
try {
setTimeout(function() {
throw new Error(); // вÑлеÑÐ¸Ñ Ð² конÑолÑ
}, 1000);
} catch (e) {
alert( "не ÑÑабоÑаеÑ" );
}
Ðа Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð·Ð°Ð¿ÑÑка ÑÑнкÑии, назнаÑенной ÑеÑез setTimeout, ÑÑÐ¾Ñ ÐºÐ¾Ð´ Ñже завеÑÑиÑÑÑ, инÑеÑпÑеÑаÑÐ¾Ñ Ð²ÑÐ¹Ð´ÐµÑ Ð¸Ð· блока try..catch.
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð¹Ð¼Ð°ÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð²Ð½ÑÑÑи ÑÑнкÑии из setTimeout, и try..catch должен бÑÑÑ Ð² Ñой же ÑÑнкÑии.
ÐбÑÐµÐºÑ Ð¾Ñибки
РпÑимеÑе вÑÑе Ð¼Ñ Ð²Ð¸Ð´Ð¸Ð¼ обÑÐµÐºÑ Ð¾Ñибки. У него еÑÑÑ ÑÑи оÑновнÑÑ ÑвойÑÑва:
name- Тип оÑибки. ÐапÑимеÑ, пÑи обÑаÑении к неÑÑÑеÑÑвÑÑÑей пеÑеменной:
"ReferenceError". message- ТекÑÑовое ÑообÑение о деÑалÑÑ Ð¾Ñибки.
stack- Ðезде, кÑоме IE8-, еÑÑÑ Ñакже ÑвойÑÑво
stack, коÑоÑое ÑодеÑÐ¶Ð¸Ñ ÑÑÑÐ¾ÐºÑ Ñ Ð¸Ð½ÑоÑмаÑией о поÑледоваÑелÑноÑÑи вÑзовов, коÑоÑÐ°Ñ Ð¿Ñивела к оÑибке.
РзавиÑимоÑÑи Ð¾Ñ Ð±ÑаÑзеÑа Ñ Ð½ÐµÐ³Ð¾ могÑÑ Ð±ÑÑÑ Ð¸ дополниÑелÑнÑе ÑвойÑÑва, Ñм. Error в MDN и Error в MSDN.
ÐÑÐ¸Ð¼ÐµÑ Ð¸ÑполÑзованиÑ
Ð JavaScript еÑÑÑ Ð²ÑÑÑоеннÑй меÑод JSON.parse(str), коÑоÑÑй иÑполÑзÑеÑÑÑ Ð´Ð»Ñ ÑÑÐµÐ½Ð¸Ñ JavaScript-обÑекÑов (и не ÑолÑко) из ÑÑÑоки.
ÐбÑÑно он иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÑабаÑÑваÑÑ Ð´Ð°Ð½Ð½Ñе, полÑÑеннÑе по ÑеÑи, Ñ ÑеÑвеÑа или из дÑÑгого иÑÑоÑника.
ÐÑ Ð¿Ð¾Ð»ÑÑаем иÑ
и вÑзÑваем меÑод JSON.parse, Ð²Ð¾Ñ Ñак:
var data = '{"name":"ÐаÑÑ", "age": 30}'; // ÑÑÑока Ñ Ð´Ð°Ð½Ð½Ñми, полÑÑÐµÐ½Ð½Ð°Ñ Ñ ÑеÑвеÑа
var user = JSON.parse(data); // пÑеобÑазовали ÑÑÑÐ¾ÐºÑ Ð² обÑекÑ
// ÑепеÑÑ user -- ÑÑо JS-обÑÐµÐºÑ Ñ Ð´Ð°Ð½Ð½Ñми из ÑÑÑоки
alert( user.name ); // ÐаÑÑ
alert( user.age ); // 30
Ðолее деÑалÑно ÑоÑÐ¼Ð°Ñ JSON ÑазобÑан в главе ФоÑÐ¼Ð°Ñ JSON, меÑод toJSON.
Ð ÑлÑÑае, еÑли даннÑе некоÑÑекÑнÑ, JSON.parse генеÑиÑÑÐµÑ Ð¾ÑибкÑ, Ñо еÑÑÑ ÑкÑÐ¸Ð¿Ñ Â«ÑпадÑÑ».
УÑÑÑÐ¾Ð¸Ñ Ð»Ð¸ Ð½Ð°Ñ Ñакое поведение? ÐонеÑно неÑ!
ÐолÑÑаеÑÑÑ, ÑÑо еÑли вдÑÑг ÑÑо-Ñо не Ñак Ñ Ð´Ð°Ð½Ð½Ñми, Ñо поÑеÑиÑÐµÐ»Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° (еÑли, конеÑно, не оÑкÑÐ¾ÐµÑ ÐºÐ¾Ð½ÑолÑ) об ÑÑом не ÑзнаеÑ.
РлÑди оÑенÑ-оÑÐµÐ½Ñ Ð½Ðµ лÑбÑÑ, когда ÑÑо-Ñо «пÑоÑÑо падаеÑ», без вÑÑкого обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± оÑибке.
ÐÑваÑÑ ÑиÑÑаÑии, когда без try..catch не обойÑиÑÑ, ÑÑо â одна из ÑакиÑ
.
ÐÑполÑзÑем try..catch, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÑабоÑаÑÑ Ð½ÐµÐºÐ¾ÑÑекÑнÑй оÑвеÑ:
var data = "Has Error"; // в даннÑÑ
оÑибка
try {
var user = JSON.parse(data); // <-- оÑибка пÑи вÑполнении
alert( user.name ); // не ÑÑабоÑаеÑ
} catch (e) {
// ...вÑполниÑÑÑ catch
alert( "ÐзвиниÑе, в даннÑÑ
оÑибка, Ð¼Ñ Ð¿Ð¾Ð¿ÑобÑем полÑÑиÑÑ Ð¸Ñ
еÑÑ Ñаз" );
alert( e.name );
alert( e.message );
}
ÐдеÑÑ Ð² alert ÑолÑко вÑводиÑÑÑ ÑообÑение, но облаÑÑÑ Ð¿ÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð³Ð¾Ñаздо ÑиÑе: можно повÑоÑÑÑÑ Ð·Ð°Ð¿ÑоÑ, можно пÑедлагаÑÑ Ð¿Ð¾ÑеÑиÑÐµÐ»Ñ Ð¸ÑполÑзоваÑÑ Ð°Ð»ÑÑеÑнаÑивнÑй ÑпоÑоб, можно оÑÑÑлаÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾Ð± оÑибке на ÑеÑвеÑ⦠Свобода дейÑÑвий.
ÐенеÑаÑÐ¸Ñ ÑÐ²Ð¾Ð¸Ñ Ð¾Ñибок
ÐÑедÑÑавим на минÑÑÑ, ÑÑо даннÑе ÑвлÑÑÑÑÑ ÐºÐ¾ÑÑекÑнÑм JSON⦠Ðо в ÑÑом обÑекÑе Ð½ÐµÑ Ð½Ñжного ÑвойÑÑва name:
var data = '{ "age": 30 }'; // даннÑе неполнÑ
try {
var user = JSON.parse(data); // <-- вÑполниÑÑÑ Ð±ÐµÐ· оÑибок
alert( user.name ); // undefined
} catch (e) {
// не вÑполниÑÑÑ
alert( "ÐзвиниÑе, в даннÑÑ
оÑибка" );
}
ÐÑзов JSON.parse вÑполниÑÑÑ Ð±ÐµÐ· оÑибок, но оÑибка в даннÑÑ
еÑÑÑ. Ð, Ñак как ÑвойÑÑво name обÑзаÑелÑно должно бÑÑÑ, Ñо Ð´Ð»Ñ Ð½Ð°Ñ ÑÑо Ñакие же некоÑÑекÑнÑе даннÑе, как и "Has Error".
ÐÐ»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑниÑиÑиÑоваÑÑ Ð¸ обÑединиÑÑ Ð¾Ð±ÑабоÑÐºÑ Ð¾Ñибок паÑÑинга и оÑибок в ÑÑÑÑкÑÑÑе, Ð¼Ñ Ð²Ð¾ÑполÑзÑемÑÑ Ð¾Ð¿ÐµÑаÑоÑом throw.
ÐпеÑаÑÐ¾Ñ throw
ÐпеÑаÑÐ¾Ñ throw генеÑиÑÑÐµÑ Ð¾ÑибкÑ.
СинÑакÑиÑ: throw <обÑÐµÐºÑ Ð¾Ñибки>.
ТеÑ
ниÑеÑки в каÑеÑÑве обÑекÑа оÑибки можно пеÑедаÑÑ ÑÑо Ñгодно, ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð´Ð°Ð¶Ðµ не обÑекÑ, а ÑиÑло или ÑÑÑока, но вÑÑ Ð¶Ðµ лÑÑÑе, ÑÑÐ¾Ð±Ñ ÑÑо бÑл обÑекÑ, желаÑелÑно â ÑовмеÑÑимÑй Ñо ÑÑандаÑÑнÑм, Ñо еÑÑÑ ÑÑÐ¾Ð±Ñ Ñ Ð½ÐµÐ³Ð¾ бÑли как минимÑм ÑвойÑÑва name и message.
РкаÑеÑÑве конÑÑÑÑкÑоÑа оÑибок можно иÑполÑзоваÑÑ Ð²ÑÑÑоеннÑй конÑÑÑÑкÑоÑ: new Error(message) или лÑбой дÑÑгой.
Ð JavaScript вÑÑÑоен ÑÑд конÑÑÑÑкÑоÑов Ð´Ð»Ñ ÑÑандаÑÑнÑÑ
оÑибок: SyntaxError, ReferenceError, RangeError и некоÑоÑÑе дÑÑгие. Ðожно иÑполÑзоваÑÑ Ð¸ иÑ
, но ÑолÑко ÑÑÐ¾Ð±Ñ Ð½Ðµ бÑло пÑÑаниÑÑ.
Рданном ÑлÑÑае Ð¼Ñ Ð¸ÑполÑзÑем конÑÑÑÑкÑÐ¾Ñ new SyntaxError(message). Ðн ÑоздаÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ñого же Ñипа, ÑÑо и JSON.parse.
var data = '{ "age": 30 }'; // даннÑе неполнÑ
try {
var user = JSON.parse(data); // <-- вÑполниÑÑÑ Ð±ÐµÐ· оÑибок
if (!user.name) {
throw new SyntaxError("ÐаннÑе некоÑÑекÑнÑ");
}
alert( user.name );
} catch (e) {
alert( "ÐзвиниÑе, в даннÑÑ
оÑибка" );
}
ÐолÑÑилоÑÑ, ÑÑо блок catch â единое меÑÑо Ð´Ð»Ñ Ð¾Ð±ÑабоÑки оÑибок во вÑеÑ
ÑлÑÑаÑÑ
: когда оÑибка вÑÑвлÑеÑÑÑ Ð¿Ñи JSON.parse или позже.
ÐÑобÑÐ¾Ñ Ð¸ÑклÑÑениÑ
Ркоде вÑÑе Ð¼Ñ Ð¿ÑедÑÑмоÑÑели обÑабоÑÐºÑ Ð¾Ñибок, коÑоÑÑе возникаÑÑ Ð¿Ñи некоÑÑекÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ . Ðо Ð¼Ð¾Ð¶ÐµÑ Ð»Ð¸ бÑÑÑ Ñак, ÑÑо Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ ÐºÐ°ÐºÐ°Ñ-Ñо дÑÑÐ³Ð°Ñ Ð¾Ñибка?
ÐонеÑно, можеÑ! Ðод â ÑÑо вообÑе меÑок Ñ Ð¾Ñибками, бÑÐ²Ð°ÐµÑ Ð´Ð°Ð¶Ðµ Ñак, ÑÑо библиоÑÐµÐºÑ Ð²ÑкладÑваÑÑ Ð² оÑкÑÑÑÑй доÑÑÑп, она Ñам 10 Ð»ÐµÑ Ð»ÐµÐ¶Ð¸Ñ, ÐµÑ ÑмоÑÑÑÑ Ð¼Ð¸Ð»Ð»Ð¸Ð¾Ð½Ñ Ð»Ñдей и на 11-й год Ð½Ð°Ñ Ð¾Ð´ÑÑÑÑ Ð¾Ð¿Ð°ÑнейÑие оÑибки. Такова жизнÑ, ÑÐ°ÐºÐ¾Ð²Ñ Ð»Ñди.
Ðлок catch в наÑем пÑимеÑе пÑедназнаÑен Ð´Ð»Ñ Ð¾Ð±ÑабоÑки оÑибок, возникаÑÑиÑ
пÑи некоÑÑекÑнÑÑ
даннÑÑ
. ÐÑли же в него попала какаÑ-Ñо дÑÑÐ³Ð°Ñ Ð¾Ñибка, Ñо вÑвод ÑообÑÐµÐ½Ð¸Ñ Ð¾ «некоÑÑекÑнÑÑ
даннÑÑ
» бÑÐ´ÐµÑ Ð´ÐµÐ·Ð¸Ð½ÑоÑмаÑией поÑеÑиÑелÑ.
ÐÑибкÑ, о коÑоÑой catch не знаеÑ, он не должен обÑабаÑÑваÑÑ.
Ð¢Ð°ÐºÐ°Ñ ÑеÑ
ника назÑваеÑÑÑ Â«Ð¿ÑобÑÐ¾Ñ Ð¸ÑклÑÑениÑ»: в catch(e) Ð¼Ñ Ð°Ð½Ð°Ð»Ð¸Ð·Ð¸ÑÑем обÑÐµÐºÑ Ð¾Ñибки, и еÑли он нам не подÑ
одиÑ, Ñо делаем throw e.
ÐÑи ÑÑом оÑибка «вÑпадаеÑ» из try..catch наÑÑжÑ. Ðалее она Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð¹Ð¼Ð°Ð½Ð° либо внеÑним блоком try..catch (еÑли еÑÑÑ), либо «повалиÑ» ÑкÑипÑ.
РпÑимеÑе ниже catch обÑабаÑÑÐ²Ð°ÐµÑ ÑолÑко оÑибки SyntaxError, а оÑÑалÑнÑе â вÑбÑаÑÑÐ²Ð°ÐµÑ Ð´Ð°Ð»ÑÑе:
var data = '{ "name": "ÐаÑÑ", "age": 30 }'; // даннÑе коÑÑекÑнÑ
try {
var user = JSON.parse(data);
if (!user.name) {
throw new SyntaxError("ÐÑибка в даннÑÑ
");
}
blabla(); // пÑоизоÑла непÑедÑÑмоÑÑÐµÐ½Ð½Ð°Ñ Ð¾Ñибка
alert( user.name );
} catch (e) {
if (e.name == "SyntaxError") {
alert( "ÐзвиниÑе, в даннÑÑ
оÑибка" );
} else {
throw e;
}
}
ÐамеÑим, ÑÑо оÑибка, коÑоÑÐ°Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ»Ð° внÑÑÑи блока catch, «вÑпадаеÑ» наÑÑжÑ, как еÑли Ð±Ñ Ð±Ñла в обÑÑном коде.
Ð ÑледÑÑÑем пÑимеÑе Ñакие оÑибки обÑабаÑÑваÑÑÑÑ ÐµÑÑ Ð¾Ð´Ð½Ð¸Ð¼, «более внеÑним» try..catch:
function readData() {
var data = '{ "name": "ÐаÑÑ", "age": 30 }';
try {
// ...
blabla(); // оÑибка!
} catch (e) {
// ...
if (e.name != 'SyntaxError') {
throw e; // пÑобÑаÑÑваем
}
}
}
try {
readData();
} catch (e) {
alert( "Ðоймал во внеÑнем catch: " + e ); // ловим
}
РпÑимеÑе вÑÑе try..catch внÑÑÑи readData ÑÐ¼ÐµÐµÑ Ð¾Ð±ÑабаÑÑваÑÑ ÑолÑко SyntaxError, а внеÑний â вÑе оÑибки.
Ðез внеÑнего пÑобÑоÑÐµÐ½Ð½Ð°Ñ Ð¾Ñибка «вÑвалилаÑÑ» Ð±Ñ Ð² конÑÐ¾Ð»Ñ Ñ Ð¾ÑÑановкой ÑкÑипÑа.
ÐбоÑаÑивание иÑклÑÑений
Ð, Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑ ÐºÐ°ÑÑÐ¸Ð½Ñ â поÑледнÑÑ, ÑÐ°Ð¼Ð°Ñ Ð¿ÑодвинÑÑÐ°Ñ ÑÐµÑ Ð½Ð¸ÐºÐ° по ÑабоÑе Ñ Ð¾Ñибками. Ðна, впÑоÑем, ÑвлÑеÑÑÑ ÑÑандаÑÑной пÑакÑикой во Ð¼Ð½Ð¾Ð³Ð¸Ñ Ð¾Ð±ÑекÑно-оÑиенÑиÑованнÑÑ ÑзÑÐºÐ°Ñ .
Ð¦ÐµÐ»Ñ ÑÑнкÑии readData в пÑимеÑе вÑÑе â пÑоÑиÑаÑÑ Ð´Ð°Ð½Ð½Ñе. ÐÑи ÑÑении могÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÑÑ ÑазнÑе оÑибки, не ÑолÑко SyntaxError, но и, возможно, к пÑимеÑÑ URIError (непÑавилÑное пÑименение ÑÑнкÑий ÑабоÑÑ Ñ URI) да и дÑÑгие.
Ðод, коÑоÑÑй вÑзвал readData, Ñ
оÑел Ð±Ñ Ð¸Ð¼ÐµÑÑ Ð»Ð¸Ð±Ð¾ ÑезÑлÑÑаÑ, либо инÑоÑмаÑÐ¸Ñ Ð¾Ð± оÑибке.
ÐÑи ÑÑом оÑÐµÐ½Ñ Ð²Ð°Ð¶Ð½Ñм ÑвлÑеÑÑÑ Ð²Ð¾Ð¿ÑоÑ: обÑзан ли ÑÑÐ¾Ñ Ð²Ð½ÐµÑний код знаÑÑ Ð¾ вÑевозможнÑÑ ÑÐ¸Ð¿Ð°Ñ Ð¾Ñибок, коÑоÑÑе могÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÑÑ Ð¿Ñи ÑÑении даннÑÑ , и ÑмеÑÑ Ð¿ÐµÑÐµÑ Ð²Ð°ÑÑваÑÑ Ð¸Ñ ?
ÐбÑÑно внеÑний код Ñ Ð¾Ñел Ð±Ñ ÑабоÑаÑÑ Â«Ð½Ð° ÑÑÐ¾Ð²ÐµÐ½Ñ Ð²ÑÑе», и полÑÑаÑÑ Ð»Ð¸Ð±Ð¾ ÑезÑлÑÑаÑ, либо «оÑÐ¸Ð±ÐºÑ ÑÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ Â», пÑи ÑÑом ÐºÐ°ÐºÐ°Ñ Ð¸Ð¼ÐµÐ½Ð½Ð¾ оÑибка пÑоизоÑла â ÐµÐ¼Ñ Ð½ÐµÐ²Ð°Ð¶Ð½Ð¾. ÐÑ, или, еÑли бÑÐ´ÐµÑ Ð²Ð°Ð¶Ð½Ð¾, Ñо Ñ Ð¾ÑелоÑÑ Ð±Ñ Ð¸Ð¼ÐµÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ ÑÑо ÑзнаÑÑ, но обÑÑно не ÑÑебÑеÑÑÑ.
ÐÑо важнейÑий обÑий Ð¿Ð¾Ð´Ñ Ð¾Ð´ к пÑоекÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ â каждÑй ÑÑаÑÑок ÑÑнкÑионалÑноÑÑи должен полÑÑаÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð½Ð° Ñом ÑÑовне, коÑоÑÑй ей Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼.
ÐÑ ÐµÐ³Ð¾ видим везде в гÑамоÑно поÑÑÑоенном коде, но не вÑегда оÑдаÑм Ñебе в ÑÑом оÑÑÑÑ.
Рданном ÑлÑÑае, еÑли пÑи ÑÑении даннÑÑ
пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¾Ñибка, Ñо Ð¼Ñ Ð±Ñдем генеÑиÑоваÑÑ ÐµÑ Ð² виде обÑекÑа ReadError, Ñ ÑооÑвеÑÑÑвÑÑÑим ÑообÑением. Р«иÑÑ
однÑÑ» оÑÐ¸Ð±ÐºÑ Ð½Ð° вÑÑкий ÑлÑÑай Ñоже ÑоÑ
Ñаним, пÑиÑвоим в ÑвойÑÑво cause (англ. â пÑиÑина).
ÐÑглÑÐ´Ð¸Ñ ÑÑо Ñак:
function ReadError(message, cause) {
this.message = message;
this.cause = cause;
this.name = 'ReadError';
this.stack = cause.stack;
}
function readData() {
var data = '{ bad data }';
try {
// ...
JSON.parse(data);
// ...
} catch (e) {
// ...
if (e.name == 'URIError') {
throw new ReadError("ÐÑибка в URI", e);
} else if (e.name == 'SyntaxError') {
throw new ReadError("СинÑакÑиÑеÑÐºÐ°Ñ Ð¾Ñибка в даннÑÑ
", e);
} else {
throw e; // пÑобÑаÑÑваем
}
}
}
try {
readData();
} catch (e) {
if (e.name == 'ReadError') {
alert( e.message );
alert( e.cause ); // оÑигиналÑÐ½Ð°Ñ Ð¾Ñибка-пÑиÑина
} else {
throw e;
}
}
ÐÑÐ¾Ñ Ð¿Ð¾Ð´Ñ
од назÑваÑÑ Â«Ð¾Ð±Ð¾ÑаÑиванием» иÑклÑÑениÑ, поÑколÑÐºÑ Ð¼Ñ Ð±ÐµÑÑм оÑибки «более низкого ÑÑовнÑ» и «завоÑаÑиваем» иÑ
в ReadError, коÑоÑÐ°Ñ ÑооÑвеÑÑÑвÑÐµÑ ÑекÑÑей задаÑе.
СекÑÐ¸Ñ finally
ÐонÑÑÑÑкÑÐ¸Ñ try..catch Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ ÐµÑÑ Ð¾Ð´Ð¸Ð½ блок: finally.
ÐÑглÑÐ´Ð¸Ñ ÑÑÐ¾Ñ ÑаÑÑиÑеннÑй ÑинÑакÑÐ¸Ñ Ñак:
try {
.. пÑобÑем вÑполниÑÑ ÐºÐ¾Ð´ ..
} catch(e) {
.. пеÑеÑ
ваÑÑваем иÑклÑÑение ..
} finally {
.. вÑполнÑем вÑегда ..
}
СекÑÐ¸Ñ finally не обÑзаÑелÑна, но еÑли она еÑÑÑ, Ñо она вÑполнÑеÑÑÑ Ð²Ñегда:
- поÑле блока
try, еÑли оÑибок не бÑло, - поÑле
catch, еÑли они бÑли.
ÐопÑобÑйÑе запÑÑÑиÑÑ Ñакой код?
try {
alert( 'try' );
if (confirm('СгенеÑиÑоваÑÑ Ð¾ÑибкÑ?')) BAD_CODE();
} catch (e) {
alert( 'catch' );
} finally {
alert( 'finally' );
}
У него два ваÑианÑа ÑабоÑÑ:
- ÐÑли Ð²Ñ Ð¾ÑвеÑиÑе на вопÑÐ¾Ñ Â«ÑгенеÑиÑоваÑÑ Ð¾ÑибкÑ?» ÑÑвеÑдиÑелÑно, Ñо
try -> catch -> finally. - ÐÑли оÑвеÑиÑе оÑÑиÑаÑелÑно, Ñо
try -> finally.
СекÑÐ¸Ñ finally иÑполÑзÑÑÑ, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð²ÐµÑÑиÑÑ Ð½Ð°ÑаÑÑе опеÑаÑии пÑи лÑбом ваÑианÑе ÑазвиÑÐ¸Ñ ÑобÑÑий.
ÐапÑимеÑ, Ð¼Ñ Ñ
оÑим подÑÑиÑаÑÑ Ð²ÑÐµÐ¼Ñ Ð½Ð° вÑполнение ÑÑнкÑии sum(n), коÑоÑÐ°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° возвÑаÑиÑÑ ÑÑÐ¼Ð¼Ñ ÑиÑел Ð¾Ñ 1 до n и ÑабоÑÐ°ÐµÑ ÑекÑÑÑивно:
function sum(n) {
return n ? (n + sum(n - 1)) : 0;
}
var n = +prompt('ÐведиÑе n?', 100);
var start = new Date();
try {
var result = sum(n);
} catch (e) {
result = 0;
} finally {
var diff = new Date() - start;
}
alert( result ? result : 'бÑла оÑибка' );
alert( "ÐÑполнение занÑло " + diff );
ÐдеÑÑ ÑекÑÐ¸Ñ finally гаÑанÑиÑÑеÑ, ÑÑо вÑÐµÐ¼Ñ Ð±ÑÐ´ÐµÑ Ð¿Ð¾Ð´ÑÑиÑано в лÑбÑÑ
ÑиÑÑаÑиÑÑ
: пÑи оÑибке в sum или без неÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе пÑовеÑиÑÑ ÑÑо, запÑÑÑив код Ñ Ñказанием n=100 â бÑÐ´ÐµÑ Ð±ÐµÐ· оÑибки, finally вÑполниÑÑÑ Ð¿Ð¾Ñле try, а заÑем Ñ n=100000 â бÑÐ´ÐµÑ Ð¾Ñибка из-за ÑлиÑком глÑбокой ÑекÑÑÑии, ÑпÑавление пÑÑÐ³Ð½ÐµÑ Ð² finally поÑле catch.
finally и returnÐлок finally ÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ñи лÑбом вÑÑ
оде из try..catch, в Ñом ÑиÑле и return.
РпÑимеÑе ниже из try пÑоиÑÑ
Ð¾Ð´Ð¸Ñ return, но finally полÑÑÐ°ÐµÑ ÑпÑавление до Ñого, как конÑÑÐ¾Ð»Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑÑÑ Ð²Ð¾ внеÑний код.
function func() {
try {
// ÑÑÐ°Ð·Ñ Ð²ÐµÑнÑÑÑ Ð·Ð½Ð°Ñение
return 1;
} catch (e) {
/* ... */
} finally {
alert( 'finally' );
}
}
alert( func() ); // ÑнаÑала finally, поÑом 1
ÐÑли внÑÑÑи try бÑли наÑаÑÑ ÐºÐ°ÐºÐ¸Ðµ-Ñо пÑоÑеÑÑÑ, коÑоÑÑе нÑжно завеÑÑиÑÑ Ð¿Ð¾ оконÑании ÑабоÑÑ, Ñо в finally ÑÑо обÑзаÑелÑно бÑÐ´ÐµÑ Ñделано.
ÐÑÑаÑи, Ð´Ð»Ñ ÑакиÑ
ÑлÑÑаев иногда иÑполÑзÑÑÑ try..finally вообÑе без catch:
function func() {
try {
return 1;
} finally {
alert( 'ÐÑзов завеÑÑÑн' );
}
}
alert( func() ); // ÑнаÑала finally, поÑом 1
РпÑимеÑе вÑÑе try..finally вообÑе не обÑабаÑÑÐ²Ð°ÐµÑ Ð¾Ñибки. ÐадаÑа в дÑÑгом: вÑполниÑÑ ÐºÐ¾Ð´ пÑи лÑбом вÑÑ
оде из try â Ñ Ð¾Ñибкой ли, без оÑибок или ÑеÑез return.
ÐоÑледнÑÑ Ð½Ð°Ð´ÐµÐ¶Ð´Ð°: window.onerror
ÐопÑÑÑим, оÑибка пÑоизоÑла вне блока try..catch или вÑпала из try..catch наÑÑжÑ, во внеÑний код. СкÑÐ¸Ð¿Ñ Ñпал.
Ðожно ли как-Ñо ÑзнаÑÑ Ð¾ Ñом, ÑÑо пÑоизоÑло? Ðа, конеÑно.
РбÑаÑзеÑе ÑÑÑеÑÑвÑÐµÑ ÑпеÑиалÑное ÑвойÑÑво window.onerror, еÑли в него запиÑаÑÑ ÑÑнкÑиÑ, Ñо она вÑполниÑÑÑ Ð¸ полÑÑÐ¸Ñ Ð² аÑгÑменÑаÑ
ÑообÑение оÑибки, ÑекÑÑий URL и Ð½Ð¾Ð¼ÐµÑ ÑÑÑоки, оÑкÑда «вÑпала» оÑибка.
ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ лиÑÑ Ð¿Ð¾Ð·Ð°Ð±Ð¾ÑиÑÑÑÑ, ÑÑÐ¾Ð±Ñ ÑÑнкÑÐ¸Ñ Ð±Ñла назнаÑена заÑанее.
ÐапÑимеÑ:
<script>
window.onerror = function(message, url, lineNumber) {
alert("Ðоймана оÑибка, вÑпавÑÐ°Ñ Ð² глобалÑнÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ!\n" +
"СообÑение: " + message + "\n(" + url + ":" + lineNumber + ")");
};
function readData() {
error(); // ой, ÑÑо-Ñо не Ñак
}
readData();
</script>
Ðак пÑавило, ÑÐ¾Ð»Ñ window.onerror заклÑÑаеÑÑÑ Ð½Ðµ в Ñом, ÑÑÐ¾Ð±Ñ Ð¾Ð¶Ð¸Ð²Ð¸ÑÑ ÑкÑÐ¸Ð¿Ñ â ÑкоÑее вÑего, ÑÑо Ñже невозможно, а в Ñом, ÑÑÐ¾Ð±Ñ Ð¾ÑоÑлаÑÑ ÑообÑение об оÑибке на ÑеÑвеÑ, где ÑазÑабоÑÑики о ней ÑзнаÑÑ.
СÑÑеÑÑвÑÑÑ Ð´Ð°Ð¶Ðµ ÑпеÑиалÑнÑе веб-ÑеÑвиÑÑ, коÑоÑÑе пÑедоÑÑавлÑÑÑ ÑкÑипÑÑ Ð´Ð»Ñ Ð¾Ñлова и аналиÑики ÑÐ°ÐºÐ¸Ñ Ð¾Ñибок, напÑимеÑ: https://errorception.com/ или https://www.muscula.com/.
ÐÑого
ÐбÑабоÑка оÑибок â болÑÑÐ°Ñ Ð¸ Ð²Ð°Ð¶Ð½Ð°Ñ Ñема.
Ð JavaScript Ð´Ð»Ñ ÑÑого пÑедÑÑмоÑÑенÑ:
-
ÐонÑÑÑÑкÑиÑ
try..catch..finallyâ она позволÑÐµÑ Ð¾Ð±ÑабоÑаÑÑ Ð¿ÑоизволÑнÑе оÑибки в блоке кода.ÐÑо Ñдобно в ÑÐµÑ ÑлÑÑаÑÑ , когда пÑоÑе ÑделаÑÑ Ð´ÐµÐ¹ÑÑвие и поÑом ÑазбиÑаÑÑÑÑ Ñ ÑезÑлÑÑаÑом, Ñем долго и нÑдно пÑовеÑÑÑÑ, не ÑпадÑÑ Ð»Ð¸ Ñего.
ÐÑоме Ñого, иногда пÑовеÑиÑÑ Ð¿ÑоÑÑо невозможно, напÑимеÑ
JSON.parse(str)не позволÑÐµÑ Â«Ð¿ÑовеÑиÑÑ» ÑоÑÐ¼Ð°Ñ ÑÑÑоки пеÑед ÑазбоÑом. Ð ÑÑом ÑлÑÑае блокtry..catchÐ½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼.ÐолнÑй вид конÑÑÑÑкÑии:
try { .. пÑобÑем вÑполниÑÑ ÐºÐ¾Ð´ .. } catch(e) { .. пеÑÐµÑ Ð²Ð°ÑÑваем иÑклÑÑение .. } finally { .. вÑполнÑем вÑегда .. }ÐÐ¾Ð·Ð¼Ð¾Ð¶Ð½Ñ Ñакже ваÑианÑÑ
try..catchилиtry..finally. -
ÐпеÑаÑоÑ
throw errгенеÑиÑÑÐµÑ ÑÐ²Ð¾Ñ Ð¾ÑибкÑ, в каÑеÑÑвеerrÑекомендÑеÑÑÑ Ð¸ÑполÑзоваÑÑ Ð¾Ð±ÑекÑÑ, ÑовмеÑÑимÑе Ñ Ð²ÑÑÑоеннÑм Ñипом Error, ÑодеÑжаÑие ÑвойÑÑваmessageиname.
ÐÑоме Ñого, Ð¼Ñ ÑаÑÑмоÑÑели некоÑоÑÑе важнÑе пÑиÑмÑ:
-
ÐÑобÑÐ¾Ñ Ð¸ÑклÑÑÐµÐ½Ð¸Ñ â
catch(err)должен обÑабаÑÑваÑÑ ÑолÑко Ñе оÑибки, коÑоÑÑе Ð¼Ñ ÑаÑÑÑиÑÑваем в нÑм ÑвидеÑÑ, оÑÑалÑнÑе â пÑобÑаÑÑваÑÑ Ð´Ð°Ð»ÑÑе ÑеÑезthrow err.ÐпÑеделиÑÑ, нÑÐ¶Ð½Ð°Ñ Ð»Ð¸ ÑÑо оÑибка, можно, напÑимеÑ, по ÑвойÑÑвÑ
name. -
ÐбоÑаÑивание иÑклÑÑений â ÑÑнкÑиÑ, в пÑоÑеÑÑе ÑабоÑÑ ÐºÐ¾ÑоÑой Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ ÑазлиÑнÑе Ð²Ð¸Ð´Ñ Ð¾Ñибок, Ð¼Ð¾Ð¶ÐµÑ Â«Ð¾Ð±ÐµÑнÑÑÑ Ð¸Ñ Â» в Ð¾Ð´Ð½Ñ Ð¾Ð±ÑÑÑ Ð¾ÑибкÑ, ÑпеÑиÑиÑнÑÑ Ð´Ð»Ñ ÐµÑ Ð·Ð°Ð´Ð°Ñи, и Ñже ÐµÑ Ð¿ÑобÑоÑиÑÑ Ð´Ð°Ð»ÑÑе. ЧÑÐ¾Ð±Ñ Ð¿Ñи Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи можно бÑло подÑобно опÑеделиÑÑ, ÑÑо пÑоизоÑло, иÑÑ Ð¾Ð´Ð½ÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð¾Ð±ÑÑно пÑиÑваиваÑÑ Ð² ÑвойÑÑво ÑÑой, обÑей. ÐбÑÑно ÑÑо нÑжно Ð´Ð»Ñ Ð»Ð¾Ð³Ð¸ÑованиÑ.
-
Ð
window.onerrorможно пÑиÑвоиÑÑ ÑÑнкÑиÑ, коÑоÑÐ°Ñ Ð²ÑполниÑÑÑ Ð¿Ñи лÑбой «вÑпавÑей» из ÑкÑипÑа оÑибке. Ðак пÑавило, ÑÑо иÑполÑзÑÑÑ Ð² инÑоÑмаÑионнÑÑ ÑелÑÑ , напÑÐ¸Ð¼ÐµÑ Ð¾ÑпÑавлÑÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾Ð± оÑибке на ÑпеÑиалÑнÑй ÑеÑвиÑ.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)