Похоже, вы рассматриваете массив ожидающих репо двумя противоречивыми способами. Внешний для l oop:
for (n = 0; n <= pendingRepos.length; n++) { ... }
обрабатывает pendingRepos
как неизменный список, проходя от начала до конца и обрабатывая каждый элемент. (И делать это неправильно тоже - мы должны итерировать до n < pendingRepos.length
, если мы используем эту опцию).
Лог c сразу после l oop, однако
subruta = pendingRepos[pendingRepos.length -1]
pendingRepos.pop()
обрабатывает pendingRepos
как изменяемый стек, из которого вы будете продолжать обрабатывать последний элемент, пока стек не будет пустым.
Чтобы правильно обработать массив, вам нужно выбрать один или другой. Поскольку кажется, что остальная часть вашего кода правильно использует подход стека, значение l oop в верхней части должно быть изменено для соответствия, что в этом случае будет просто
while (pendingRepos.length > 0) { ... }
Конечный результат будет выглядит следующим образом:
while (pendingRepos.length > 0){
const subruta = pendingRepos[pendingRepos.length -1]
pendingRepos.pop()
c.list(subruta, function(err, sublist) {
if (sublist.length != 0){
for (let g = 0; g < sublist.length; g++){
if (sublist[g].type === 'd' ){
repositories.push(subruta+'/'+sublist[g].name)
pendingRepos.push(subruta+'/'+sublist[g].name)
} else {
files.push(subruta+'/'+sublist[g].name)
}
}
}
});
}
РЕДАКТИРОВАТЬ: Приведенный выше ответ работает только в том случае, если c.list()
является синхронной функцией, которая немедленно запускает ваш обратный вызов перед возвратом - однако, поскольку это связаться с FTP-сервером, это не так. Это означает, что все while
l oop завершится sh до запуска любого из этих обратных вызовов, и все, что они добавят к pendingRepos
, не будет обработано. Чтобы использовать асинхронные функции, вы должны структурировать свою функцию совершенно по-разному, в основном используя все больше и больше асинхронных функций, насколько это возможно. go.
К счастью, сделать это довольно легко в этом случае. То, что вы делаете с pendingRepos
, концептуально известно как поиск в глубину (или «DFS») , где вы выполняете поиск по древовидной структуре, повторяя поиск на каждом подузле. Использование стека ожидающих каталогов является одним из способов создания DFS, а другой способ сделать это - использовать рекурсивную функцию (в основном повторяя функцию поиска каждый раз, когда вы достигаете каталога).
Вот возможная реализация что с использованием обратных вызовов, расширяющих весь путь.
// an outer function for the whole operation. You would provide
// a callback that takes the lists of repositories and files.
function getTheRepos(startList, callbackForWholeThing) {
// build up our lists of repositories and files
const repositories = [];
const files = [];
// keep track of how many calculations are running
let repoGetCount = 0;
// an inner function to run exactly one result
function getOneRepo(subruta) {
// at the start, say we're running
repoGetCount++;
c.list(subruta, function(err, sublist) {
if (sublist.length != 0){
for (let g = 0; g < sublist.length; g++){
if (sublist[g].type === 'd' ){
repositories.push(subruta+'/'+sublist[g].name)
// for each directory we find, call this inner function again.
// This is the critical part that makes this all work.
getOneRepo(subruta+'/'+sublist[g].name)
} else {
files.push(subruta+'/'+sublist[g].name)
}
}
// at the end, say we're not running,
// and call the whole callback if we're the last one
repoGetCount--;
if (repoGetCount === 0) {
callbackForWholeThing(repositories, files);
}
}
});
// now that we have the function, run it on each of our
// start directories to start things off
for (let n = 0; n < startList.length; n++) {
getOneRepo(startList[n]);
}
// the cogs are in motion, so now return.
// The callback will be called when the tree has been searched.
}