ÐÐ»Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑии иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð»Ð±Ñков, пÑомиÑов и дÑÑÐ³Ð¸Ñ Ð°Ð±ÑÑÑакÑнÑÑ Ð¿Ð¾Ð½ÑÑий Ð¼Ñ Ð±Ñдем иÑполÑзоваÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе бÑаÑзеÑнÑе меÑодÑ: в ÑаÑÑноÑÑи, загÑÑÐ·ÐºÑ ÑкÑипÑов и вÑполнение пÑоÑÑÑÑ Ð¼Ð°Ð½Ð¸Ð¿ÑлÑÑий Ñ Ð´Ð¾ÐºÑменÑом.
ÐÑли Ð²Ñ Ð½Ðµ Ð·Ð½Ð°ÐºÐ¾Ð¼Ñ Ñ ÑÑими меÑодами, и Ð¸Ñ Ð¸ÑполÑзование в пÑимеÑÐ°Ñ Ð²ÑзÑÐ²Ð°ÐµÑ Ñ Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñмение, возможно, вам ÑÑÐ¾Ð¸Ñ Ð¿ÑоÑиÑаÑÑ Ð½ÐµÑколÑко глав из ÑледÑÑÑей ÑаÑÑи ÑÑебника.
Тем не менее, Ð¼Ñ Ð²Ñе Ñавно попÑÑаемÑÑ Ð¼Ð°ÐºÑималÑно Ð´Ð¾Ñ Ð¾Ð´Ñиво вÑÑ ÑазÑÑÑниÑÑ. ÐиÑего оÑобо Ñложного в плане бÑаÑзеÑа не бÑдеÑ.
Ðногие дейÑÑÐ²Ð¸Ñ Ð² JavaScript аÑÐ¸Ð½Ñ ÑоннÑе.
ÐапÑимеÑ, ÑаÑÑмоÑÑим ÑÑнкÑÐ¸Ñ loadScript(src):
function loadScript(src) {
let script = document.createElement('script');
script.src = src;
document.head.append(script);
}
ÐÑа ÑÑнкÑÐ¸Ñ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ Ð½Ð° ÑÑÑаниÑÑ Ð½Ð¾Ð²Ñй ÑкÑипÑ. Ðогда в Ñело докÑменÑа добавиÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ <script src="â¦">, бÑаÑÐ·ÐµÑ Ð·Ð°Ð³ÑÑÐ·Ð¸Ñ ÑкÑÐ¸Ð¿Ñ Ð¸ вÑÐ¿Ð¾Ð»Ð½Ð¸Ñ ÐµÐ³Ð¾.
ÐÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑой ÑÑнкÑии:
// загÑÑÐ·Ð¸Ñ Ð¸ вÑÐ¿Ð¾Ð»Ð½Ð¸Ñ ÑкÑипÑ
loadScript('/my/script.js');
Такие ÑÑнкÑии назÑваÑÑ Â«Ð°ÑÐ¸Ð½Ñ ÑоннÑми», поÑÐ¾Ð¼Ñ ÑÑо дейÑÑвие (загÑÑзка ÑкÑипÑа) бÑÐ´ÐµÑ Ð·Ð°Ð²ÐµÑÑено не ÑейÑаÑ, а поÑом.
ÐÑли поÑле вÑзова loadScript(â¦) еÑÑÑ ÐºÐ°ÐºÐ¾Ð¹-Ñо код, Ñо он не бÑÐ´ÐµÑ Ð¶Ð´Ð°ÑÑ, пока ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑзиÑÑÑ.
loadScript('/my/script.js');
// код, напиÑаннÑй поÑле вÑзова ÑÑнкÑии loadScript,
// не бÑÐ´ÐµÑ Ð´Ð¾Ð¶Ð¸Ð´Ð°ÑÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ загÑÑзки ÑкÑипÑа
// ...
ÐÑ Ñ Ð¾Ñели Ð±Ñ Ð¸ÑполÑзоваÑÑ Ð½Ð¾Ð²Ñй ÑкÑипÑ, как ÑолÑко он бÑÐ´ÐµÑ Ð·Ð°Ð³ÑÑжен. Скажем, он обÑÑвлÑÐµÑ Ð½Ð¾Ð²ÑÑ ÑÑнкÑиÑ, коÑоÑÑÑ Ð¼Ñ Ñ Ð¾Ñим вÑполниÑÑ.
Ðо еÑли Ð¼Ñ Ð¿ÑоÑÑо вÑзовем ÑÑÑ ÑÑнкÑÐ¸Ñ Ð¿Ð¾Ñле loadScript(â¦), Ñ Ð½Ð°Ñ Ð½Ð¸Ñего не вÑйдеÑ:
loadScript('/my/script.js'); // в ÑкÑипÑе еÑÑÑ "function newFunction() {â¦}"
newFunction(); // Ñакой ÑÑнкÑии не ÑÑÑеÑÑвÑеÑ!
ÐейÑÑвиÑелÑно, Ð²ÐµÐ´Ñ Ñ Ð±ÑаÑзеÑа не бÑло вÑемени загÑÑзиÑÑ ÑкÑипÑ. СейÑÐ°Ñ ÑÑнкÑÐ¸Ñ loadScript никак не позволÑÐµÑ Ð¾ÑÑледиÑÑ Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð·Ð°Ð³ÑÑзки. СкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑжаеÑÑÑ, а поÑом вÑполнÑеÑÑÑ. Ðо нам нÑжно ÑоÑно знаÑÑ, когда ÑÑо пÑоизойдÑÑ, ÑÑÐ¾Ð±Ñ Ð¸ÑполÑзоваÑÑ ÑÑнкÑии и пеÑеменнÑе из ÑÑого ÑкÑипÑа.
ÐавайÑе пеÑедадим ÑÑнкÑÐ¸Ñ callback вÑоÑÑм аÑгÑменÑом в loadScript, ÑÑÐ¾Ð±Ñ Ð²ÑзваÑÑ ÐµÑ, когда ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑзиÑÑÑ:
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(script);
document.head.append(script);
}
СобÑÑие onload опиÑано в ÑÑаÑÑе ÐагÑÑзка ÑеÑÑÑÑов: onload и onerror, оно в оÑновном вÑполнÑÐµÑ ÑÑнкÑÐ¸Ñ Ð¿Ð¾Ñле загÑÑзки и вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑкÑипÑа.
ТепеÑÑ, еÑли Ð¼Ñ Ñ Ð¾Ñим вÑзваÑÑ ÑÑнкÑÐ¸Ñ Ð¸Ð· ÑкÑипÑа, нÑжно делаÑÑ ÑÑо в колбÑке:
loadScript('/my/script.js', function() {
// ÑÑа ÑÑнкÑÐ¸Ñ Ð²ÑзовеÑÑÑ Ð¿Ð¾Ñле Ñого, как загÑÑзиÑÑÑ ÑкÑипÑ
newFunction(); // ÑепеÑÑ Ð²ÑÑ ÑабоÑаеÑ
...
});
СмÑÑл Ñакой: вÑоÑÑм аÑгÑменÑом пеÑедаÑÑÑÑ ÑÑнкÑÐ¸Ñ (обÑÑно анонимнаÑ), коÑоÑÐ°Ñ Ð²ÑполнÑеÑÑÑ Ð¿Ð¾ завеÑÑении дейÑÑвиÑ.
ÐозÑмÑм Ð´Ð»Ñ Ð¿ÑимеÑа ÑеалÑнÑй ÑкÑÐ¸Ð¿Ñ Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñекой ÑÑнкÑий:
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(script);
document.head.append(script);
}
loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
alert(`ÐдоÑово, ÑкÑÐ¸Ð¿Ñ ${script.src} загÑÑзилÑÑ`);
alert( _ ); // ÑÑнкÑиÑ, обÑÑÐ²Ð»ÐµÐ½Ð½Ð°Ñ Ð² загÑÑженном ÑкÑипÑе
});
Такое напиÑание назÑваÑÑ Ð°ÑинÑ
ÑоннÑм пÑогÑаммиÑованием Ñ Ð¸ÑполÑзованием колбÑков. Ð ÑÑнкÑии, коÑоÑÑе вÑполнÑÑÑ ÐºÐ°ÐºÐ¸Ðµ-либо аÑинÑ
ÑоннÑе опеÑаÑии, пеÑедаÑÑÑÑ Ð°ÑгÑÐ¼ÐµÐ½Ñ callback â ÑÑнкÑиÑ, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð²Ñзвана по завеÑÑÐµÐ½Ð¸Ñ Ð°ÑинÑ
Ñонного дейÑÑвиÑ.
ÐÑ Ð¿Ð¾ÑÑÑпили поÑ
ожим обÑазом в loadScript, но ÑÑо, конеÑно, ÑаÑпÑоÑÑÑанÑннÑй подÑ
од.
ÐолбÑк в колбÑке
Ðак нам загÑÑзиÑÑ Ð´Ð²Ð° ÑкÑипÑа один за дÑÑгим: ÑнаÑала пеÑвÑй, а за ним вÑоÑой?
ÐеÑвое, ÑÑо пÑиÑ
Ð¾Ð´Ð¸Ñ Ð² головÑ, вÑзваÑÑ loadScript еÑÑ Ñаз Ñже внÑÑÑи колбÑка, Ð²Ð¾Ñ Ñак:
loadScript('/my/script.js', function(script) {
alert(`ÐдоÑово, ÑкÑÐ¸Ð¿Ñ ${script.src} загÑÑзилÑÑ, загÑÑзим еÑÑ Ð¾Ð´Ð¸Ð½`);
loadScript('/my/script2.js', function(script) {
alert(`ÐдоÑово, вÑоÑой ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑзилÑÑ`);
});
});
Ðогда внеÑнÑÑ ÑÑнкÑÐ¸Ñ loadScript вÑполниÑÑÑ, вÑзовеÑÑÑ Ñа, ÑÑо внÑÑÑи колбÑка.
Ð ÑÑо еÑли нам нÑжно загÑÑзиÑÑ ÐµÑÑ Ð¾Ð´Ð¸Ð½ ÑкÑипÑ?..
loadScript('/my/script.js', function(script) {
loadScript('/my/script2.js', function(script) {
loadScript('/my/script3.js', function(script) {
// ...и Ñак далее, пока вÑе ÑкÑипÑÑ Ð½Ðµ бÑдÑÑ Ð·Ð°Ð³ÑÑженÑ
});
})
});
Ðаждое новое дейÑÑвие Ð¼Ñ Ð²ÑнÑÐ¶Ð´ÐµÐ½Ñ Ð²ÑзÑваÑÑ Ð²Ð½ÑÑÑи колбÑка. ÐÑÐ¾Ñ Ð²Ð°ÑÐ¸Ð°Ð½Ñ Ð¿Ð¾Ð´Ð¾Ð¹Ð´ÑÑ, когда Ñ Ð½Ð°Ñ Ð¾Ð´Ð½Ð¾-два дейÑÑвиÑ, но Ð´Ð»Ñ Ð±Ð¾Ð»ÑÑего колиÑеÑÑва Ñже не Ñдобно. ÐлÑÑеÑнаÑивнÑе Ð¿Ð¾Ð´Ñ Ð¾Ð´Ñ Ð¼Ñ ÑкоÑо ÑазбеÑÑм.
ÐеÑÐµÑ Ð²Ð°Ñ Ð¾Ñибок
РпÑимеÑÐ°Ñ Ð²ÑÑе Ð¼Ñ Ð½Ðµ дÑмали об оÑÐ¸Ð±ÐºÐ°Ñ . Ð ÑÑо еÑли загÑÑзиÑÑ ÑкÑÐ¸Ð¿Ñ Ð½Ðµ ÑдалоÑÑ? ÐолбÑк должен ÑмеÑÑ ÑеагиÑоваÑÑ Ð½Ð° возможнÑе пÑоблемÑ.
Ðиже ÑлÑÑÑÐµÐ½Ð½Ð°Ñ Ð²ÐµÑÑÐ¸Ñ loadScript, коÑоÑÐ°Ñ ÑÐ¼ÐµÐµÑ Ð¾ÑÑлеживаÑÑ Ð¾Ñибки загÑÑзки:
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Ðе ÑдалоÑÑ Ð·Ð°Ð³ÑÑзиÑÑ ÑкÑÐ¸Ð¿Ñ ${src}`));
document.head.append(script);
}
ÐÑ Ð²ÑзÑваем callback(null, script) в ÑлÑÑае ÑÑпеÑной загÑÑзки и callback(error), еÑли загÑÑзиÑÑ ÑкÑÐ¸Ð¿Ñ Ð½Ðµ ÑдалоÑÑ.
Ðивой пÑимеÑ:
loadScript('/my/script.js', function(error, script) {
if (error) {
// обÑабаÑÑваем оÑибкÑ
} else {
// ÑкÑÐ¸Ð¿Ñ ÑÑпеÑно загÑÑжен
}
});
ÐпÑÑÑ Ð¶Ðµ, подÑ
од, коÑоÑÑй Ð¼Ñ Ð¸ÑполÑзовали в loadScript, Ñакже ÑаÑпÑоÑÑÑанÑн и назÑваеÑÑÑ Â«ÐºÐ¾Ð»Ð±Ñк Ñ Ð¿ÐµÑвÑм аÑгÑменÑом-оÑибкой» («error-first callback»).
ÐÑавила ÑаковÑ:
- ÐеÑвÑй аÑгÑÐ¼ÐµÐ½Ñ ÑÑнкÑии
callbackзаÑезеÑвиÑован Ð´Ð»Ñ Ð¾Ñибки. Ð ÑÑом ÑлÑÑае вÑзов вÑглÑÐ´Ð¸Ñ Ð²Ð¾Ñ Ñак:callback(err). - ÐÑоÑой и поÑледÑÑÑие аÑгÑменÑÑ â Ð´Ð»Ñ ÑезÑлÑÑаÑов вÑполнениÑ. Ð ÑÑом ÑлÑÑае вÑзов вÑглÑÐ´Ð¸Ñ Ð²Ð¾Ñ Ñак:
callback(null, result1, result2â¦).
Ðдна и Ñа же ÑÑнкÑÐ¸Ñ callback иÑполÑзÑеÑÑÑ Ð¸ Ð´Ð»Ñ Ð¸Ð½ÑоÑмиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð± оÑибке, и Ð´Ð»Ñ Ð¿ÐµÑедаÑи ÑезÑлÑÑаÑов.
ÐдÑÐºÐ°Ñ Ð¿Ð¸Ñамида вÑзовов
Ðа пеÑвÑй взглÑд ÑÑо ÑабоÑий ÑпоÑоб напиÑÐ°Ð½Ð¸Ñ Ð°ÑÐ¸Ð½Ñ Ñонного кода. Так и еÑÑÑ. ÐÐ»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ или двÑÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½ÑÑ Ð²Ñзовов вÑÑ Ð²ÑглÑÐ´Ð¸Ñ Ð½Ð¾ÑмалÑно.
Ðо Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ Ð°ÑÐ¸Ð½Ñ ÑоннÑÑ Ð´ÐµÐ¹ÑÑвий, коÑоÑÑе нÑжно вÑполниÑÑ Ð´ÑÑг за дÑÑгом, код вÑглÑÐ´Ð¸Ñ Ð²Ð¾Ñ Ñак:
loadScript('1.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...и Ñак далее, пока вÑе ÑкÑипÑÑ Ð½Ðµ бÑдÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐ½Ñ (*)
}
});
}
})
}
});
РпÑимеÑе вÑÑе:
- ÐÑ Ð·Ð°Ð³ÑÑжаем
1.js. ÐÑодолжаем, еÑли Ð½ÐµÑ Ð¾Ñибок. - ÐÑ Ð·Ð°Ð³ÑÑжаем
2.js. ÐÑодолжаем, еÑли Ð½ÐµÑ Ð¾Ñибок. - ÐÑ Ð·Ð°Ð³ÑÑжаем
3.js. ÐÑодолжаем, еÑли Ð½ÐµÑ Ð¾Ñибок. Ð Ñак далее(*).
Чем болÑÑе вложеннÑÑ
вÑзовов, Ñем Ð½Ð°Ñ ÐºÐ¾Ð´ бÑÐ´ÐµÑ Ð¸Ð¼ÐµÑÑ Ð²ÑÑ Ð±Ð¾Ð»ÑÑÑÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾ÑÑÑ, коÑоÑÑÑ Ñложно поддеÑживаÑÑ, оÑобенно еÑли вмеÑÑо ... Ñ Ð½Ð°Ñ ÐºÐ¾Ð´, ÑодеÑжаÑий дÑÑгие ÑепоÑки вÑзовов, ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ Ñ.д.
Ðногда ÑÑо назÑваÑÑ Â«Ð°Ð´Ð¾Ð¼ колбÑков» или «адÑкой пиÑамидой колбÑков».
ÐиÑамида вложеннÑÑ Ð²Ñзовов ÑаÑÑÑÑ Ð²Ð¿Ñаво Ñ ÐºÐ°Ð¶Ð´Ñм аÑÐ¸Ð½Ñ ÑоннÑм дейÑÑвием. РиÑоге Ð²Ñ Ñами бÑдеÑе пÑÑаÑÑÑÑ, где ÑÑо еÑÑÑ.
Такой Ð¿Ð¾Ð´Ñ Ð¾Ð´ к напиÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð´Ð° не пÑивеÑÑÑвÑеÑÑÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ попÑÑаÑÑÑÑ ÑеÑиÑÑ ÑÑÑ Ð¿ÑоблемÑ, изолиÑÑÑ ÐºÐ°Ð¶Ð´Ð¾Ðµ дейÑÑвие в оÑделÑнÑÑ ÑÑнкÑиÑ, Ð²Ð¾Ñ Ñак:
loadScript('1.js', step1);
function step1(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', step2);
}
}
function step2(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', step3);
}
}
function step3(error, script) {
if (error) {
handleError(error);
} else {
// ...и Ñак далее, пока вÑе ÑкÑипÑÑ Ð½Ðµ бÑдÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐ½Ñ (*)
}
};
ÐамеÑили? ÐÑÐ¾Ñ ÐºÐ¾Ð´ Ð´ÐµÐ»Ð°ÐµÑ Ð²ÑÑ Ñо же Ñамое, но вложенноÑÑÑ Ð¾ÑÑÑÑÑÑвÑеÑ, поÑÐ¾Ð¼Ñ ÑÑо вÑе дейÑÑÐ²Ð¸Ñ Ð²ÑнеÑÐµÐ½Ñ Ð² оÑделÑнÑе ÑÑнкÑии.
Ðод абÑолÑÑно ÑабоÑий, но кажеÑÑÑ ÑазоÑваннÑм на кÑÑки. Ðго ÑÑÑдно ÑиÑаÑÑ, Ð²Ñ Ð½Ð°Ð²ÐµÑнÑка замеÑили ÑÑо. ÐÑÐ¸Ñ Ð¾Ð´Ð¸ÑÑÑ Ð¿ÑÑгаÑÑ Ð³Ð»Ð°Ð·Ð°Ð¼Ð¸ Ð¼ÐµÐ¶Ð´Ñ ÐºÑÑками кода, когда пÑÑаеÑÑÑÑ ÐµÐ³Ð¾ пÑоÑеÑÑÑ. ÐÑо неÑдобно, оÑобенно, еÑли ÑиÑаÑÐµÐ»Ñ Ð½Ðµ знаком Ñ ÐºÐ¾Ð´Ð¾Ð¼ и не знаеÑ, ÑÑо за Ñем ÑледÑеÑ.
ÐÑоме Ñого, вÑе ÑÑнкÑии step* одноÑазовÑе, и ÑÐ¾Ð·Ð´Ð°Ð½Ñ Ð»Ð¸ÑÑ ÑолÑко, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±Ð°Ð²Ð¸ÑÑÑÑ Ð¾Ñ Â«Ð°Ð´Ñкой пиÑÐ°Ð¼Ð¸Ð´Ñ Ð²Ñзовов». ÐикÑо не бÑÐ´ÐµÑ Ð¸Ñ
пеÑеиÑполÑзоваÑÑ Ð³Ð´Ðµ-либо еÑÑ. Таким обÑазом, мÑ, кÑоме вÑего пÑоÑего, заÑоÑÑем пÑоÑÑÑанÑÑво имÑн.
ÐÑжно найÑи ÑпоÑоб полÑÑÑе.
Ð ÑÑаÑÑÑÑ, Ñакие ÑпоÑÐ¾Ð±Ñ ÑÑÑеÑÑвÑÑÑ. Ðдин из лÑÑÑÐ¸Ñ â иÑполÑзоваÑÑ Ð¿ÑомиÑÑ, о коÑоÑÑÑ ÑаÑÑказано в ÑледÑÑÑей главе.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)