ÐÑаÑÐ·ÐµÑ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð¾ÑÑлеживаÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ ÑÑоÑÐ¾Ð½Ð½Ð¸Ñ ÑеÑÑÑÑов: ÑкÑипÑов, иÑÑеймов, изобÑажений и дÑ.
ÐÐ»Ñ ÑÑого ÑÑÑеÑÑвÑÑÑ Ð´Ð²Ð° ÑобÑÑиÑ:
loadâ ÑÑпеÑÐ½Ð°Ñ Ð·Ð°Ð³ÑÑзка,errorâ во вÑÐµÐ¼Ñ Ð·Ð°Ð³ÑÑзки пÑоизоÑла оÑибка.
ÐагÑÑзка ÑкÑипÑов
ÐопÑÑÑим, нам нÑжно загÑÑзиÑÑ ÑÑоÑонний ÑкÑÐ¸Ð¿Ñ Ð¸ вÑзваÑÑ ÑÑнкÑиÑ, коÑоÑÐ°Ñ Ð¾Ð±ÑÑвлена в ÑÑом ÑкÑипÑе.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ загÑÑзиÑÑ ÑÑÐ¾Ñ ÑкÑÐ¸Ð¿Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑки:
let script = document.createElement('script');
script.src = "my.js";
document.head.append(script);
â¦Ðо как нам вÑзваÑÑ ÑÑнкÑиÑ, коÑоÑÐ°Ñ Ð¾Ð±ÑÑвлена внÑÑÑи Ñого ÑкÑипÑа? Ðам нÑжно подождаÑÑ, пока ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑзиÑÑÑ, и ÑолÑко поÑом Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÐµÑ Ð²ÑзваÑÑ.
ÐÐ»Ñ Ð½Ð°ÑÐ¸Ñ ÑобÑÑвеннÑÑ ÑкÑипÑов Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ JavaScript-модÑли, но они не ÑлиÑком ÑиÑоко ÑаÑпÑоÑÑÑÐ°Ð½ÐµÐ½Ñ Ð² ÑÑоÑÐ¾Ð½Ð½Ð¸Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾ÑÐµÐºÐ°Ñ .
script.onload
ÐлавнÑй помоÑник â ÑÑо ÑобÑÑие load. Ðно ÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ð¾Ñле Ñого, как ÑкÑÐ¸Ð¿Ñ Ð±Ñл загÑÑжен и вÑполнен.
ÐапÑимеÑ:
let script = document.createElement('script');
// Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ загÑÑзиÑÑ Ð»Ñбой ÑкÑÐ¸Ð¿Ñ Ñ Ð»Ñбого домена
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"
document.head.append(script);
script.onload = function() {
// в ÑкÑипÑе ÑоздаÑÑÑÑ Ð²ÑпомогаÑелÑÐ½Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ "_"
alert(_.VERSION); // оÑобÑÐ°Ð¶Ð°ÐµÑ Ð²ÐµÑÑÐ¸Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñеки
};
Таким обÑазом, в обÑабоÑÑике onload Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð¿ÐµÑеменнÑе, вÑзÑваÑÑ ÑÑнкÑии и Ñ.д., коÑоÑÑе пÑедоÑÑавлÑÐµÑ Ð½Ð°Ð¼ ÑÑоÑонний ÑкÑипÑ.
â¦Ð ÑÑо еÑли во вÑÐµÐ¼Ñ Ð·Ð°Ð³ÑÑзки пÑоизоÑла оÑибка? ÐапÑимеÑ, Ñакого ÑкÑипÑа Ð½ÐµÑ (оÑибка 404), или ÑеÑÐ²ÐµÑ Ð±Ñл недоÑÑÑпен.
script.onerror
ÐÑибки, коÑоÑÑе возникаÑÑ Ð²Ð¾ вÑÐµÐ¼Ñ Ð·Ð°Ð³ÑÑзки ÑкÑипÑа, могÑÑ Ð±ÑÑÑ Ð¾ÑÑÐ»ÐµÐ¶ÐµÐ½Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑобÑÑÐ¸Ñ error.
ÐапÑимеÑ, давайÑе запÑоÑим ÑкÑипÑ, коÑоÑого не ÑÑÑеÑÑвÑеÑ:
let script = document.createElement('script');
script.src = "https://example.com/404.js"; // Ñакого Ñайла не ÑÑÑеÑÑвÑеÑ
document.head.append(script);
script.onerror = function() {
alert("ÐÑибка загÑÑзки " + this.src); // ÐÑибка загÑÑзки https://example.com/404.js
};
ÐбÑаÑиÑе внимание, ÑÑо Ð¼Ñ Ð½Ðµ можем полÑÑиÑÑ Ð¾Ð¿Ð¸Ñание HTTP-оÑибки. ÐÑ Ð½Ðµ знаем, бÑла ли ÑÑо оÑибка 404 или 500, или какаÑ-Ñо дÑÑгаÑ. Ðнаем ÑолÑко, ÑÑо во вÑÐµÐ¼Ñ Ð·Ð°Ð³ÑÑзки пÑоизоÑла оÑибка.
ÐбÑабоÑÑики onload/onerror оÑÑлеживаÑÑ ÑолÑко Ñам пÑоÑеÑÑ Ð·Ð°Ð³ÑÑзки.
ÐÑибки обÑабоÑки и вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð³ÑÑженного ÑкÑипÑа ими не оÑÑлеживаÑÑÑÑ. ЧÑÐ¾Ð±Ñ Â«Ð¿Ð¾Ð¹Ð¼Ð°ÑÑ» оÑибки в ÑкÑипÑе, нÑжно воÑполÑзоваÑÑÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑм обÑабоÑÑиком window.onerror.
ÐÑÑгие ÑеÑÑÑÑÑ
СобÑÑÐ¸Ñ load и error Ñакже ÑÑабаÑÑваÑÑ Ð¸ Ð´Ð»Ñ Ð´ÑÑгиÑ
ÑеÑÑÑÑов, а вообÑе, Ð´Ð»Ñ Ð»ÑбÑÑ
ÑеÑÑÑÑов, Ñ ÐºÐ¾ÑоÑÑÑ
еÑÑÑ Ð²Ð½ÐµÑний src.
ÐапÑимеÑ:
let img = document.createElement('img');
img.src = "https://js.cx/clipart/train.gif"; // (*)
img.onload = function() {
alert(`ÐзобÑажение загÑÑжено, ÑазмеÑÑ ${img.width}x${img.height}`);
};
img.onerror = function() {
alert("ÐÑибка во вÑÐµÐ¼Ñ Ð·Ð°Ð³ÑÑзки изобÑажениÑ");
};
Ðднако еÑÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе оÑобенноÑÑи:
- ÐолÑÑинÑÑво ÑеÑÑÑÑов наÑинаÑÑ Ð·Ð°Ð³ÑÑжаÑÑÑÑ Ð¿Ð¾Ñле иÑ
Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² докÑменÑ. Ðа иÑклÑÑением Ñега
<img>. ÐзобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°ÑинаÑÑ Ð·Ð°Ð³ÑÑжаÑÑÑÑ, когда полÑÑаÑÑsrc (*). - ÐлÑ
<iframe>ÑобÑÑиеloadÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ð¾ оконÑании загÑÑзки как в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°, Ñак и в ÑлÑÑае оÑибки.
Такое поведение ÑложилоÑÑ Ð¿Ð¾ иÑÑоÑиÑеÑким пÑиÑинам.
ÐÑибка в ÑкÑипÑе Ñ Ð´ÑÑгого иÑÑоÑника
ÐÑÑÑ Ð¿Ñавило: ÑкÑипÑÑ Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ ÑайÑа не могÑÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð´Ð¾ÑÑÑп к ÑодеÑÐ¶Ð¸Ð¼Ð¾Ð¼Ñ Ð´ÑÑгого ÑайÑа. ÐапÑимеÑ, ÑкÑÐ¸Ð¿Ñ Ñ https://facebook.com не Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑоÑиÑаÑÑ Ð¿Ð¾ÑÑÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð½Ð° https://gmail.com.
Ðли, еÑли бÑÑÑ Ð±Ð¾Ð»ÐµÐµ ÑоÑнÑм, один иÑÑоÑник (домен/поÑÑ/пÑоÑокол) не Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð´Ð¾ÑÑÑп к ÑодеÑÐ¶Ð¸Ð¼Ð¾Ð¼Ñ Ñ Ð´ÑÑгого иÑÑоÑника. Ðаже поддомен или пÑоÑÑо дÑÑгой поÑÑ Ð±ÑдÑÑ ÑÑиÑаÑÑÑÑ ÑазнÑми иÑÑоÑниками, не имеÑÑими доÑÑÑпа дÑÑг к дÑÑгÑ.
ÐÑо пÑавило Ñакже каÑаеÑÑÑ ÑеÑÑÑÑов Ñ Ð´ÑÑÐ³Ð¸Ñ Ð´Ð¾Ð¼ÐµÐ½Ð¾Ð².
ÐÑли Ð¼Ñ Ð¸ÑполÑзÑем ÑкÑÐ¸Ð¿Ñ Ñ Ð´ÑÑгого домена, и в нем имееÑÑÑ Ð¾Ñибка, Ð¼Ñ Ð½Ðµ Ñможем ÑзнаÑÑ Ð´ÐµÑали ÑÑой оÑибки.
ÐÐ»Ñ Ð¿ÑимеÑа давайÑе возÑмÑм мини-ÑкÑÐ¸Ð¿Ñ error.js, коÑоÑÑй ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· одного-единÑÑвенного вÑзова ÑÑнкÑии, коÑоÑой не ÑÑÑеÑÑвÑеÑ:
// ð error.js
noSuchFunction();
ТепеÑÑ Ð·Ð°Ð³ÑÑзим ÑÑÐ¾Ñ ÑкÑÐ¸Ð¿Ñ Ñ Ñого же ÑайÑа, на коÑоÑом он лежиÑ:
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="/article/onload-onerror/crossorigin/error.js"></script>
ÐÑ Ð²Ð¸Ð´Ð¸Ð¼ ноÑмалÑнÑй оÑÑÑÑ Ð¾Ð± оÑибке:
Uncaught ReferenceError: noSuchFunction is not defined
https://javascript.info/article/onload-onerror/crossorigin/error.js, 1:1
Ð ÑепеÑÑ Ð·Ð°Ð³ÑÑзим ÑÑÐ¾Ñ Ð¶Ðµ ÑкÑÐ¸Ð¿Ñ Ñ Ð´ÑÑгого домена:
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
ÐÑÑÑÑ Ð¾ÑлиÑаеÑÑÑ:
Script error.
, 0:0
ÐеÑали оÑÑÑÑа могÑÑ Ð²Ð°ÑÑиÑоваÑÑÑÑ Ð² завиÑимоÑÑи Ð¾Ñ Ð±ÑаÑзеÑа, но оÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð¸Ð´ÐµÑ Ð¾ÑÑаÑÑÑÑ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½Ð½Ð¾Ð¹: лÑÐ±Ð°Ñ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ внÑÑÑеннем ÑÑÑÑойÑÑве ÑкÑипÑа, вклÑÑÐ°Ñ ÑÑек оÑибки, ÑпÑÑÑана. Ðменно поÑомÑ, ÑÑо ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑжен Ñ Ð´ÑÑгого домена.
ÐаÑем нам могÑÑ Ð±ÑÑÑ Ð½ÑÐ¶Ð½Ñ Ð´ÐµÑали оÑибки?
СÑÑеÑÑвÑÐµÑ Ð¼Ð½Ð¾Ð³Ð¾ ÑеÑвиÑов (и Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑделаÑÑ Ð½Ð°Ñ ÑобÑÑвеннÑй), коÑоÑÑе обÑабаÑÑваÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑе оÑибки пÑи помоÑи window.onerror, ÑоÑ
ÑанÑÑÑ Ð¾ÑÑÑÑ Ð¾ ниÑ
и пÑедоÑÑавлÑÑÑ Ð´Ð¾ÑÑÑп к ÑÑÐ¾Ð¼Ñ Ð¾ÑÑÑÑÑ Ð´Ð»Ñ Ð°Ð½Ð°Ð»Ð¸Ð·Ð°. ÐÑо здоÑово, поÑÐ¾Ð¼Ñ ÑÑо Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑвидеÑÑ ÑеалÑнÑе оÑибки, коÑоÑÑе ÑлÑÑилиÑÑ Ñ Ð½Ð°ÑиÑ
полÑзоваÑелей. Ðо еÑли ÑкÑÐ¸Ð¿Ñ â Ñ Ð´ÑÑгого домена, Ñо инÑоÑмаÑии об оÑибкаÑ
в нÑм поÑÑи неÑ, как Ð¼Ñ ÑолÑко ÑÑо видели.
ÐÐ¾Ñ Ð¾Ð¶Ð°Ñ ÐºÑоÑÑ-Ð´Ð¾Ð¼ÐµÐ½Ð½Ð°Ñ Ð¿Ð¾Ð»Ð¸Ñика (CORS) внедÑена и в оÑноÑении дÑÑÐ³Ð¸Ñ ÑеÑÑÑÑов.
ЧÑÐ¾Ð±Ñ ÑазÑеÑиÑÑ ÐºÑоÑÑ-доменнÑй доÑÑÑп, нам нÑжно поÑÑавиÑÑ ÑÐµÐ³Ñ <script> аÑÑибÑÑ crossorigin, и, кÑоме Ñого, ÑдалÑннÑй ÑеÑÐ²ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ поÑÑавиÑÑ ÑпеÑиалÑнÑе заголовки.
СÑÑеÑÑвÑÐµÑ ÑÑи ÑÑÐ¾Ð²Ð½Ñ ÐºÑоÑÑ-доменного доÑÑÑпа:
- ÐÑÑибÑÑ
crossoriginоÑÑÑÑÑÑвÑÐµÑ â доÑÑÑп запÑеÑÑн. crossorigin="anonymous"â доÑÑÑп ÑазÑеÑÑн, еÑли ÑеÑÐ²ÐµÑ Ð¾ÑвеÑÐ°ÐµÑ Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð¼Access-Control-Allow-OriginÑо знаÑениÑми*или Ð½Ð°Ñ Ð´Ð¾Ð¼ÐµÐ½. ÐÑаÑÐ·ÐµÑ Ð½Ðµ оÑпÑавлÑÐµÑ Ð°Ð²ÑоÑизаÑионнÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¸ кÑки на ÑдалÑннÑй ÑеÑвеÑ.crossorigin="use-credentials"â доÑÑÑп ÑазÑеÑÑн, еÑли ÑеÑÐ²ÐµÑ Ð¾ÑвеÑÐ°ÐµÑ Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°Ð¼Ð¸Access-Control-Allow-OriginÑо знаÑением Ð½Ð°Ñ Ð´Ð¾Ð¼ÐµÐ½ иAccess-Control-Allow-Credentials: true. ÐÑаÑÐ·ÐµÑ Ð¾ÑпÑавлÑÐµÑ Ð°Ð²ÑоÑизаÑионнÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¸ кÑки на ÑдалÑннÑй ÑеÑвеÑ.
ÐоÑиÑаÑÑ Ð±Ð¾Ð»ÑÑе о кÑоÑÑ-доменнÑÑ
доÑÑÑпаÑ
Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе в главе Fetch: запÑоÑÑ Ð½Ð° дÑÑгие ÑайÑÑ. Там опиÑан меÑод fetch Ð´Ð»Ñ ÑеÑевÑÑ
запÑоÑов, но полиÑика Ñам ÑоÑно ÑÐ°ÐºÐ°Ñ Ð¶Ðµ.
Такое понÑÑие как «кÑки» (cookies) не ÑаÑÑмаÑÑиваеÑÑÑ Ð² ÑекÑÑей главе, но Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе поÑиÑаÑÑ Ð¾ Ð½Ð¸Ñ Ð² главе ÐÑки, document.cookie.
РнаÑем ÑлÑÑае аÑÑибÑÑ crossorigin оÑÑÑÑÑÑвовал. ÐоÑÑÐ¾Ð¼Ñ ÐºÑоÑÑ-доменнÑй доÑÑÑп бÑл запÑеÑÑн. ÐавайÑе добавим его.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ вÑбÑаÑÑ "anonymous" (кÑки не оÑпÑавлÑÑÑÑÑ, ÑÑебÑеÑÑÑ Ð¾Ð´Ð¸Ð½ ÑеÑвеÑнÑй заголовок) или "use-credentials" (кÑки оÑпÑавлÑÑÑÑÑ, ÑÑебÑÑÑÑÑ Ð´Ð²Ð° ÑеÑвеÑнÑÑ
заголовка) в каÑеÑÑве знаÑÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑа.
ÐÑли кÑки Ð½Ð°Ñ Ð½Ðµ волнÑÑÑ, Ñогда Ñмело вÑбиÑаем "anonymous":
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script crossorigin="anonymous" src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
ТепеÑÑ Ð¿Ñи ÑÑловии, ÑÑо ÑеÑÐ²ÐµÑ Ð¿ÑедоÑÑавил заголовок Access-Control-Allow-Origin, вÑÑ Ñ
оÑоÑо. У Ð½Ð°Ñ ÐµÑÑÑ Ð¿Ð¾Ð»Ð½Ñй оÑÑÑÑ Ð¿Ð¾ оÑибкам.
ÐÑого
ÐзобÑÐ°Ð¶ÐµÐ½Ð¸Ñ <img>, внеÑние ÑÑили, ÑкÑипÑÑ Ð¸ дÑÑгие ÑеÑÑÑÑÑ Ð¿ÑедоÑÑавлÑÑÑ ÑобÑÑÐ¸Ñ load и error Ð´Ð»Ñ Ð¾ÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð³ÑÑзки:
loadÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ñи ÑÑпеÑной загÑÑзке,errorÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ñи оÑибке загÑÑзки.
ÐдинÑÑвенное иÑклÑÑение â ÑÑо <iframe>: по иÑÑоÑиÑеÑким пÑиÑинам ÑÑабаÑÑÐ²Ð°ÐµÑ Ð²Ñегда load вне завиÑимоÑÑи Ð¾Ñ Ñого, как завеÑÑилаÑÑ Ð·Ð°Ð³ÑÑзка, даже еÑли ÑÑÑаниÑа не бÑла найдена.
СобÑÑие readystatechange Ñакже ÑабоÑÐ°ÐµÑ Ð´Ð»Ñ ÑеÑÑÑÑов, но иÑполÑзÑеÑÑÑ Ñедко, поÑÐ¾Ð¼Ñ ÑÑо ÑобÑÑÐ¸Ñ load/error пÑоÑе в иÑполÑзовании.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)