Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Варианты подгрузки данных


Автор: diam 7.4.2005, 09:28
Здраствуйте.

Опять возвращаюсь к старой теме: подгрузка данных без перезагрузки страницы.

Дано:
1. Большая и тяжёлая страница, с кучей-кучей объектов js, картинок и текста.
2. Узкий канал.

Задача:
Подгружать данные в виде кода JavaScript без перезагрузки страницы.



Я вижу следующие варианты решения данной задачи:
1. Метод appendChild ( или replaceChild, что бы не плодить дополнительных скриптов).
Суть в следующем:
а) создаём новый элемент типа script
б) задаём его свойства type = text/javascript и src = <откуда_грузить>
в) говорим appendChild(этот_элемент).
Код

<!--  вырезано -->
<script type="text/javascript">
function uploadData ( params2src ) {
        _params2src  =  params2src || "";
        var uploaded_script = document.createElement("SCRIPT");
        uploaded_script.type="text/javascript";
        uploaded_script.src= "/upload/?" + _params2src;
        document.body.appendChild(uploaded_script);
}
uploadData('param1=var1');
</script>
<!--  вырезано -->

На стороне сервера (/upload) генерируется текст
alert('Вы передали: <%=param%> = <%=value%>');
для каждой переданной пары param=value;

Таким образом, параметры передаются методом GET.

Работает это в IE 5+(младше не проверял), Gecko, Opera (7.5+, младше не проверял).
В нашем случае выскочит окошко с надписью "Вы передали: param1 = value1".
Не работает: в Konqueror (что есть большой минус, ИМХО).

На мой взгляд, метод имеет много плюсов, например то, что можно передавать любые данные: текст, объекты JS, в общем, любые типы данных JS.

2. IFRAME.
Суть метода: делаешь невидимый IFRAME, в который при необходимости заливаешь данные перезагрузкой оного, потом, после загрузки, достаёшь из него полученный текст, eval() его и вот тебе код JS.
Но, на мой взгляд, тут есть много минусов:
а. Изменяется история браузера.
б. Появляется кнопочка <back> в браузере, при нажатии на которую Вы попадаете на свою же страницу smile
в. Во всяких ИЕ щелчки раздаются.
г. Работает дольше, чем первый метод.

Но плюсы в том, что работать будет в гораздо большем числе браузеров, чем в методе 1.
Может быть и можно как-то избавиться от минусов а) и б), но я пока не знаю как. Но вот от минусов в) и г) точно не избавиться.




------------------------------------------------
Как решить задачу?
Можно ли написать API в виде объекта JS, который позволит её решать на любом браузере (эх, мечты, мечты... smile ), или на самых таких популярных, как ИЕ, опера, geck'и, конквуеры, нетшкафы и т.п.?

В общем, To Be or Not to Be, that is question. :^)

Автор: DDT 7.4.2005, 09:40
Я как раз ищу что-то подобное. Ты прямо к чаю smile


У меня вопрос по первому способу:
что должно подгружаться файл JavaScript или можно, например, РНР

Автор: diam 7.4.2005, 09:46
У меня подгружается текст, сгенерированный psp.
Да, можно использовать php. Вот только в psp у меня установлено
req.content_type = "text/javascript"
А в php, по моему, контент всегда тот, что указан в апаче (то есть, по дефолту, "text/html"); но это не означает, что работать не будет. Работает и под php.

Автор: diam 7.4.2005, 14:07
Немного меняю метод 1.
Дело в том, что если запрос будет одинаковым, например, постоянно будет запрашиваться "/upload/?", то Opera и IE будут кэшировать запрос. А это не есть гуд, нам оно не надо.
Избежать сие можно лишь каждый раз меняя адрес добавляемого элемента <script>. Адрес, конечно, мы менять не будем, но вот один параметр введём как обязательный и будем постоянно его изменять(он должен быть уникальным) (смотрим класс clUploadData(), элемент this.callID):
Код

<!--  вырезано -->
<script type="text/javascript">
function clUploadData ( thesrc ) {
        // устанавливаем адрес подгрузки
        this.src = thesrc || "/upload/";
        // подгружаться будет методом GET
        this.src += "?";
        // естественно - тип подгружаемого элемента - text/javascript
        this.type = "text/javascript";
        this.oldScript  = document.createElement("SCRIPT");
        this.oldScript.type = this.type;
        this.callId = 0;
        document.body.appendChild(this.oldScript);
        this.upload = function ( theparams ) {
                //Параметры передаются в виде par1=val1&par2=val2&...
                var tParams = theparams || "";
                var newScript = document.createElement("SCRIPT");
                newScript.type = this.type;
                // Каждый раз строка с адресом скрипта должна быть разной, иначе
                // ИЕ и Опера кэшуруют запрос. Поэтому мы меняем callid, каждый раз
                // увеличивая его на 1.
                this.callId += 1;
                newScript.src  = this.src + "callid=" + String(this.callId) + tParams;
                // Обратите внимание. Для добавления используем метод
                // replaceChild, а не appendChild, поскольку после нескольких тысяч
                // подгрузок размер документа раздуется до офигенных размеров
                document.body.replaceChild(newScript,this.oldScript);
                this.oldScript = newScript;
        }
}
// Теперь мы создаём экземпляр класса и работаем с ним
var uploadObject = new clUploadData();
// передавая параметры методом get.
uploadObject.upload("par1=val1&par2=val2");
</script>
<!--  вырезано -->



Есть ещё одно НО. Запрос передаётся методом GET, а посему имеет ограничения - объём передаваемых данных в запросе - 4 килобайта. Поэтому данные большего размера придётся или бить, или извращаться ещё каким-либо образом (например, открывать новое окошко с предложением ввести картинку smile). В общем, вот так вот.

Автор: Sardar 8.4.2005, 00:57
Зовётся это дело ajax по моему, слышал что готовые либы есть, сам не использовал. Большая проблема это выбор минимальных требований. Например в Опера 6 метод appendChild не работает.
Если веб проект использует подобные фишки то не стоит оборачиватся на старые браузеры, себе дороже. Лучше вообще заюзать обьект XMLHTTPRequest, который поддерживается ИЕ6, Мозилла и Опера 8, а на всех остальных забить. Плюсы: скорость, простота, большая "мощь".

Автор: Guest 8.4.2005, 06:46
Sardar, а IFRAME? Может, кто-то написал кроссбраузерный объект, опирающийся на IFRAME?

Автор: DDT 8.4.2005, 09:36
файл по адресу: http://msc/?sid=3&ssid=3:

Код

<script type="text/javascript">

function uploadData()
{
    var uploaded_script = document.createElement("SCRIPT");
    uploaded_script.type="text/javascript";
    uploaded_script.src= "/1.js";
    document.body.appendChild(uploaded_script);
}

uploadData();
</script>


1.js:
Код

alert("AAA");


При выполнении файла http://msc/?sid=3&ssid=3 выдается сообщение ААА, а за ним следующее:
Цитата
Не удалось открыть узел http://msc/?sid=3&ssid=3. Операция прервана.


И выдается страница
Цитата
Сервер не найден: Невозможно отобразить страницу.


Почему не удается открыть узел?

Автор: DDT 8.4.2005, 10:24
Все, вопрос сниямается. Разобрался.

Создал в документе форму с именем form.

Строку:
Код

document.body.appendChild(uploaded_script);


Заменил на:
Код

document.form.appendChild(uploaded_script);


Все пошло. И без фреймов.

Автор: Aliance 8.4.2005, 12:29
Цитата(Sardar @ 8.4.2005, 01:57)
который поддерживается ИЕ6, Мозилла и Опера 8, а на всех остальных забить

А NN?

DDT
Пользуйтесь клавишей code, немного подредактировал Ваш пост.

Автор: Gregof 11.4.2005, 13:30
http://dklab.ru/chicken/nablas/41.html

Автор: diam 11.4.2005, 18:25
Для себя решил, что через год-полтора можно будет использовать XMLHttpRequest. Только потому, что последний поддерживает метод POST. Вот только 7-ю оперу использует сейчас ну очень много народа. smile

Автор: diam 12.4.2005, 07:31
Метод подразумевает подгрузку методом GET. Это несёт с собой несколько минусов:
1. В логах запросов Apache будет видно, что запрашивают. Например, вот мой лог запроса:
Цитата
(127.0.0.1 - - [08/Apr/2005:17:09:58 +0600] "GET /upload/?callid=27&bid=12&chack=2 HTTP/1.1" 200 56 "http://localhost/" "Opera/7.54 (X11; FreeBSD i386; U)  [en]")

2. Объём передаваемых данных не может превышать 4096 байтов (это спецификация HTTP).

Но и имеет один плюс (несомненный): работает в Opera7, Gecko, IE5. А это большинство браузеров, ИМХО.

Автор: Aliance 25.5.2005, 16:52
М
 

Подчистил тему. Удалил весь оффтоп и прочее.
Готовое решение, предоставленное diam, можно увидить здесь. nJoy;-)


Автор: Diesel Draft 3.9.2005, 09:01
можно использувать и другой метод
Код

var fso = new ActiveXObject("Scripting.FileSystemObject");
var myfule = fso.OpenTextFile(filepath, 1);
...

Автор: Aliance 3.9.2005, 11:39
Diesel Draft
ActiveX работает только в среде JScript, так что только его использование преведет к отсутствию кроссбраузерности smile

Автор: ChPuK 9.3.2007, 08:32
diam, спасибо smile
прочел твой пост! у меня таже проблема была smile
разобрался сразу

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)