Javascript
Статистика
Reklama 2Under.ru
кино, фильмы, видео
музыка и MP3
авто и мото
знакомства
заработок в сети
игры
форекс, forex
женские сайты
для взрослых
строительство и ремонт
недвижимость
бытовая техника
здоровье и медицина
красота, косметика
работа, вакансии, резюме
животные и растения
детские товары
знакомства для интима
софт
развлечения
одежда и обувь
туризм и отдых
мебель, интерьер
компьютеры и оргтехника
реклама и интернет
промышленное оборудование
сырье и материалы
социальные сети
средства связи
образование и обучение
WmLink
LiveClix
Реклама от LiveCLiX
Понедельник, 06.05.2024, 13:49
Приветствую Вас Гость | RSS
Главная | Регистрация | Вход
Асинхронные вызовы

Асинхронные вызовы



Но использование reduce a.k.a fold для суммирования списков — очень упрощенный пример. Идея гораздо мощнее. Давайте разберем еще один пример.

Одна из проблем использования Javascript в браузере заключается в том, что все выполняется в одном потоке, и поэтому мы должны использовать коллбеки. 

Задача.
  • Загрузить несколько скриптов
  • Склеить их
  • сохранить порядок скриптов при склейке

То есть надо написать функцию примерно такого вида:

combine(["/jquery.js",
 "/underscore.js",
 "/backbone.js"], function(content){
 // content должен содержать все скрипты, склеенные в правильном порядке.
 });



Напишем реализацию функции combine. Сначала — лобовой подход.
function combine(scripts, callback){
 var data [];
 for(var i =0; l = scripts.length; i< l; ++i){
 // ....
 }
}


Для получения скриптов было бы логично использовать jQuery.ajax:

function combine(scripts, callback){
 var data [];
 for(var i =0; l = scripts.length; i< l; ++i){
 jQuery.ajax({

 url: scripts[i],
 success : function(response){
 // ....
 }
 });
 }
}

Подобный код не будет тормозить браузер, поскольку запросы к серверу будут отправлены асинхронно. То есть при выполнении будет 3 параллельных запроса.

Напишем обработчик для успешного скачивания скрипта.

function combine(scripts, callback){
 var data [];
 for(var i =0; l = scripts.length; i< l; ++i){
 jQuery.ajax({

 url: scripts[i],
 success : function(response){
 data[i] = response;
 if(data.length === scripts.length){
 callback(data.join(""));
 }
 }
 });
 }
}


Вроде бы функция готова. Но есть два но.
Во-первых уродливо, во-вторых — оно не будет работать.

С чем тут могут быть проблемы? С областями видимости Javascript. В этом языке область видимость не поблочная, а функциональная. то есть все 3 функции будут видеть одно и то значение переменной i. Поскольку цикл отработает раньше, чем придут ответы от сервера, все три функции будут работать с i == 3;
Эта проблема решается стандартным способом — мы кэшируем значение переменной цикла. Но нельзя сказать, что код от этого стал красивее. 

function combine(scripts, callback){
 var data [];
 for(var i =0; l = scripts.length; i< l; ++i){
 (function (i){
 jQuery.ajax({

 url: scripts[i],
 success : function(response){
 data[i] = response;
 if(data.length === scripts.length){
 callback(data.join(""));
 }
 }
 });
 }(i));
 }
}


Почти даже работает. Для того, чтобы избавиться от замыканий и хитрых переменных, можно использовать foreach

function combine(scripts, callback){
 var data [];
 scripts.forEach(function(script,i){
 jQuery.ajax({

 url: scripts[i],
 success : function(response){
 data[i] = response;
 if(data.length === scripts.length){
 callback(data.join(""));
 }
 }
 });
 });
 }
}


Лучше, конечно, но все равно страшновато. Кстати, код все еще не будет работать правильно. Его можно допилить до работоспособного состояния, но это создаст дополнительные сложности и в разработке и в последующей поддержке.
Copyright MyCorp © 2024
Сделать бесплатный сайт с uCoz