Имя: Пароль:
IT
Веб-мастеринг
Как сделать рекурсивную функцию с ожиданием?
,
0 Помогите
 
16.10.13
12:09
Нужно чтобы внутри функции было ожидание события. Как это сделать?
Например такая функция:

function next(i){
    a.load(i);
//тут нужно подождать a.onload
    next(i+1);
}
1 Помогите
 
16.10.13
12:10
javascript
2 Eugene_life
 
16.10.13
12:15
А цикл не подойдет для этого?
3 Помогите
 
16.10.13
12:34
(2) если только в цикле можно будет как-то сделать ожидание события a.onload
4 Eugene_life
 
16.10.13
12:35
джавой я не владею, так что кроме идеи ничем не смогу помочь.
5 Помогите
 
16.10.13
12:41
жаль
6 smaharbA
 
16.10.13
12:42
a.onload=function(){alert(123)}


a - это чего ?
7 Kreont
 
16.10.13
12:44
посмотри в сторону jquery, там готовые методы есть, тем более если javascript знаешь то быстро разберешся
8 Помогите
 
16.10.13
12:56
(6) гуд.

а - какой-то абстрактный объект, событие которого нужно ждать
9 Помогите
 
16.10.13
13:01
function next(i){
    a.load(i);
    a.onload=function(){next(i+1);}
}
10 Помогите
 
16.10.13
13:01
Спасибо!
Осталось разобраться почему не всегда срабатывает...
11 Asmody
 
16.10.13
13:03
(9) строки местами поменяй
12 Лефмихалыч
 
16.10.13
13:08
jscript - это грёбаное вуду...
13 Помогите
 
16.10.13
13:24
(11) у меня и было наоборот в рабочей программе.
14 NS
 
16.10.13
13:26
(4) Это не java.
15 Rie
 
16.10.13
13:26
(0) Дык, как уже было верно замечено выше, это - хвостовая рекурсия, то бишь, цикл во всей его красе.
Но вопрос - зачем ждать в цикле? Тебе две функции надо: первая - инициализировать, вторая - обработать событие.
16 y88
 
16.10.13
13:29
setTimeout(Function, Delay);
17 Asmody
 
16.10.13
13:31
тут еще очень интересна природа объекта a, ибо в варианте (0) a - глобальный объект, так что переназначать в рекурсии обработчик особого смысла не имеет.
18 Помогите
 
16.10.13
13:44
(17) как тогда передать параметры в функцию обработчика если не переназначать ее?
19 NS
 
16.10.13
13:52
(18) Зачем передавать? Делаешь i глобальной переменной, и при обработке увеличиваешь на единицу.
20 Rie
 
16.10.13
13:53
(18) Классная штука - closure.
21 uno-group
 
16.10.13
14:00
ИМХо в 7 ябы делал като так.
ОброботкаОжидания("a.load",10)//10 секунд ожидания. А И делать глобальной переменной иувеличивать по на добности. без всяких скриптов.
22 Asmody
 
16.10.13
14:01
(18) а тут многое от задачи зависит
23 Asmody
 
16.10.13
14:02
(19) и что? мы же не можем гарантировать порядок наступления событий
24 NS
 
16.10.13
14:13
(23) Не понял. Что ты имеешь в виду?
25 NS
 
16.10.13
14:15
function next(){
    a.load(i);
    i=i+1;
}
a.onload=function(){next();}
26 Asmody
 
16.10.13
14:46
(25) так это не совсем то, что в (0)
27 NS
 
16.10.13
14:48
(26) Это копия того что в (0)
28 Asmody
 
16.10.13
14:51
(27) да ладно!
29 Asmody
 
16.10.13
14:51
может по старинке по шагам пройтись?
30 NS
 
16.10.13
14:55
в (0) a.load(i);
Нужно подождать onload, и запустить с i=i+1.
в (25) Ровно тоже самое.
(29) Давай.
Запускаем.
i=1;
Next();

Выполняется a.load(1);i=i+1 (i=2)
ждет onload. после этого запускается Next();
a.load(2);i=i+1 (i=3)
ждет onload. после этого запускается Next();
a.load(3);i=i+1 (i=4) и т.д.
31 Помогите
 
17.10.13
06:10
Как бы это все не то. Потому что нет возврата в вызывающую функцию из дочерней функции. Получается не рекурсия, а линейный вызов.
Задача вообще такая: Пробежаться по дереву каталогов, и загрузить все найденные файлы.

Условно "a.load(i)" - загружает файл "i"

"i = i + 1" - это переход к следующему файлу или каталогу или провал в подкаталог. Поэтому нужен возврат из функции в то место где она была вызвана, чтобы продолжить с того же места стека.

Либо придется делать свой искусственный стек в отдельном массиве, что не хотелось бы.
32 kokamoonga
 
17.10.13
06:45
(31) а не проще пробежаться по дереву, собрать все в очередь и потом спокойно загрузить все файлы из очереди?
33 Помогите
 
17.10.13
07:08
(32) хрен знает сколько памяти эта очередь будет занимать, и сколько доступно для скрипта. Когда делал как в (9) без setTimeout, то стека хватало на ~50 файлов.

Сейчас сделал со своим стеком, работает нормально.

Но идея отличная, спасибо. Может переделаю, попробую таким способом тоже.
34 Помогите
 
17.10.13
07:11
вот, рабочий код, проверял только в IE 11:

var files, folders, a;
var arrFolders = [];

function nextFile() {
    if (!files.atEnd()){
        if( i = files.item() ) {
            a.oncanplay = function() { files.moveNext(); console.log (this.currentSrc + " !!!!"); setTimeout(function() { nextFile() }, 0) };
            a.onerror = function() { files.moveNext(); console.log (this.currentSrc + " ----"); setTimeout(function() { nextFile() }, 0) };
            a.setAttribute("src", i.Path);
            a.load();
        }
    } else {
        if ( !folders.atEnd() ){
            if ( f = folders.item() ) {
                arrFolders.push(folders);
                files = new Enumerator(f.files);
                folders = new Enumerator(f.SubFolders);
                console.log (f.Path + " #######");
                setTimeout( function() { nextFile() }, 0 );
            } else {
                folders.moveNext();
                setTimeout( function() { nextFile() }, 0 );
            }
        } else {
            if ( folders = arrFolders.pop() ) {
                folders.moveNext();
                setTimeout( function() { nextFile() }, 0 );
            }
        }
    }
}


    var FSO =  new ActiveXObject("Scripting.FileSystemObject");
    a = new Audio();

    var f = FSO.GetFolder("A:\\Флэшка в машину с музыкой");
    a.preload = "none";
    files = new Enumerator(f.files);
    folders = new Enumerator(f.SubFolders);

    nextFile(files, a, folders);
35 kokamoonga
 
17.10.13
07:22
(33) если есть проблемы с доступной памятью (что мне довольно сложно представить в случае если в массив собрать пути к файлам), тогда почему не бы не использовать localStorage?

сохранять очередь кусками по 100/1000/10000/etc в localStorage и потом также кусками вычитывать.
36 Помогите
 
17.10.13
07:26
(35) так точно не буду делать. Будем надеяться что хватит памяти. Или оставлю как есть.
37 Помогите
 
17.10.13
08:09
перенес и удалил лишнее:


function nextFile() {
    if (!files.atEnd()){
            a.setAttribute("src", files.item().Path);
            a.load();
    } else {
        if ( !folders.atEnd() ){
                arrFolders.push(folders);
                files = new Enumerator(folders.item().files);
                folders = new Enumerator(folders.item().SubFolders);
                setTimeout( function() { nextFile() }, 0 );
        } else {
            if ( folders = arrFolders.pop() ) {
                folders.moveNext();
                setTimeout( function() { nextFile(); }, 0 );
            }
        }
    }
}
38 kokamoonga
 
17.10.13
09:00
(37) эээ...

здесь второе "=" тоже оказалось лишним?

if ( folders = arrFolders.pop() )

тут присваивание вместо сравнения же
39 Помогите
 
17.10.13
10:04
(38) там переменной folders присваивается извлеченное значение из массива arrFolders. Это вроде как стек, самодельный.
40 NS
 
17.10.13
10:13
(31) именно так и делают, переписывают рекурсию на стеке.
обход дерева на стеке - это совсем просто.
1. добавляем в стек корень.
2. снимаем с стека значение.
3. добавляем в стек все дочерние.
4. к пункту 2.
41 Помогите
 
17.10.13
13:14
(40) так и было сделано.
Программист всегда исправляет последнюю ошибку.