Node.js 如何检测多个数组的多个异步调用何时完成
How to detect when multiple asynchronous calls for multiple arrays are complete in Node.js
我正在使用 [ssh2-sftp-client][1] 包递归读取给定远程路径中的所有目录。
这是代码。
const argv = require('yargs').argv;
const client = require('ssh-sftp-client');
const server = new Client();
const auth = {
host: '192.168.1.11',
username: argv.u,
password: argv.p
};
const serverRoot = '/sites/';
const siteName = 'webmaster.com';
// list of directories on the server will be pushed to this array
const serverPaths = [];
server.connect(auth).then(() => {
console.log(`connected to ${auth.host} as ${auth.username}`);
}).catch((err) => {
if (err) throw err;
});
server.list('/sites/').then((dirs) => {
redursiveDirectorySearch(dirs, `${serverRoot}${siteName}/`);
})
.catch((err) => {
if (err) throw err;
});
function recursiveDirectorySearch(dirs, prevPath) {
let paths = dirs.filter((dir) => {
// returns directories only
return dir.type === 'd';
});
if (paths.length > 0) {
paths.forEach((path) => {
server
.list(`${prevPath}${path.name}`)
.then((dirs) => {
console.log(`${prevPath}${path.name}`);
recursiveDirectorySearch(dirs, `${prevPath}${path.name}`);
serverPaths.push(`${prevPath}${path.name}`);
})
}
}
}
首先,将与服务器建立连接,然后列出“/sites/”目录下的所有内容,然后将其传递给 'recursiveDirectorySearch' 函数。此函数将接收在服务器上的“/sites/”目录下找到的任何内容的数组作为第一个参数,该参数将被过滤掉,因此它只有目录。如果找到一个或多个目录,将为数组中的每个目录调用服务器,以便检索“/sites/”+'name of the directory in the array' 下的所有内容。将使用调用服务器返回的任何内容再次调用相同的函数,直到找不到其他目录。
每当找到一个目录时,它在字符串中的名称将被推送到 'serverPaths' 数组。据我所知,此搜索正在运行并成功将所有目录名称推送到数组。
但是,我想不出一种方法来检测对所有目录的递归搜索何时完成,因此我可以对 'serverPaths' 数组做一些事情。
我尝试利用 Promise.all() 但不知道在进行了多少次函数调用时如何使用它。
最让我吃惊的事情之一是您最初的 if 语句。 (if paths.length > 0) { 运行 recursion } 这对于第一次调用似乎非常有效,因为您知道返回的数据将填充一个充满目录的数组。
但是,您的函数似乎没有为长度为 0 的数组构建逻辑。在这种情况下,您可以获取所有要查找的目录名称。以您正在寻找的方式呈现。这也意味着您对树较高部分的调用永远无法解决。
尝试添加逻辑来处理长度为零的数组的情况 |如果(paths.length === 0)return; |这将是对堆栈较高部分的递归调用的硬突破。
您只是缺少几个 return
,添加一个 Promise.all
和一个 Array#map
,您就完成了
注意:不在 serverPaths
上使用 Promise.all
,而是使用在 .then
中返回 Promise 的事实将导致由 [=16= 返回的 Promise ] 接受返回的 Promise(嗯,这不是很好解释,是吗,但它确实是 Promises 101 的东西!
server.list('/sites/').then((dirs) => {
// added a return here
return recursiveDirectorySearch(dirs, `${serverRoot}${siteName}/`);
})
.then(() => {
// everything is done at this point,
// serverPaths should be complete
})
.catch((err) => {
if (err) throw err;
});
function recursiveDirectorySearch(dirs, prevPath) {
let paths = dirs.filter((dir) => {
// returns directories only
return dir.type === 'd';
});
// added a return, Promise.all and changed forEach to map
return Promise.all(paths.map((path) => {
//added a return here
return server
.list(`${prevPath}${path.name}`)
.then((dirs) => {
console.log(`${prevPath}${path.name}`);
// swapped the next two lines
serverPaths.push(`${prevPath}${path.name}`);
// added a return here, push the path before
return recursiveDirectorySearch(dirs, `${prevPath}${path.name}`);
})
}));
}
我正在使用 [ssh2-sftp-client][1] 包递归读取给定远程路径中的所有目录。
这是代码。
const argv = require('yargs').argv;
const client = require('ssh-sftp-client');
const server = new Client();
const auth = {
host: '192.168.1.11',
username: argv.u,
password: argv.p
};
const serverRoot = '/sites/';
const siteName = 'webmaster.com';
// list of directories on the server will be pushed to this array
const serverPaths = [];
server.connect(auth).then(() => {
console.log(`connected to ${auth.host} as ${auth.username}`);
}).catch((err) => {
if (err) throw err;
});
server.list('/sites/').then((dirs) => {
redursiveDirectorySearch(dirs, `${serverRoot}${siteName}/`);
})
.catch((err) => {
if (err) throw err;
});
function recursiveDirectorySearch(dirs, prevPath) {
let paths = dirs.filter((dir) => {
// returns directories only
return dir.type === 'd';
});
if (paths.length > 0) {
paths.forEach((path) => {
server
.list(`${prevPath}${path.name}`)
.then((dirs) => {
console.log(`${prevPath}${path.name}`);
recursiveDirectorySearch(dirs, `${prevPath}${path.name}`);
serverPaths.push(`${prevPath}${path.name}`);
})
}
}
}
首先,将与服务器建立连接,然后列出“/sites/”目录下的所有内容,然后将其传递给 'recursiveDirectorySearch' 函数。此函数将接收在服务器上的“/sites/”目录下找到的任何内容的数组作为第一个参数,该参数将被过滤掉,因此它只有目录。如果找到一个或多个目录,将为数组中的每个目录调用服务器,以便检索“/sites/”+'name of the directory in the array' 下的所有内容。将使用调用服务器返回的任何内容再次调用相同的函数,直到找不到其他目录。
每当找到一个目录时,它在字符串中的名称将被推送到 'serverPaths' 数组。据我所知,此搜索正在运行并成功将所有目录名称推送到数组。
但是,我想不出一种方法来检测对所有目录的递归搜索何时完成,因此我可以对 'serverPaths' 数组做一些事情。
我尝试利用 Promise.all() 但不知道在进行了多少次函数调用时如何使用它。
最让我吃惊的事情之一是您最初的 if 语句。 (if paths.length > 0) { 运行 recursion } 这对于第一次调用似乎非常有效,因为您知道返回的数据将填充一个充满目录的数组。
但是,您的函数似乎没有为长度为 0 的数组构建逻辑。在这种情况下,您可以获取所有要查找的目录名称。以您正在寻找的方式呈现。这也意味着您对树较高部分的调用永远无法解决。
尝试添加逻辑来处理长度为零的数组的情况 |如果(paths.length === 0)return; |这将是对堆栈较高部分的递归调用的硬突破。
您只是缺少几个 return
,添加一个 Promise.all
和一个 Array#map
,您就完成了
注意:不在 serverPaths
上使用 Promise.all
,而是使用在 .then
中返回 Promise 的事实将导致由 [=16= 返回的 Promise ] 接受返回的 Promise(嗯,这不是很好解释,是吗,但它确实是 Promises 101 的东西!
server.list('/sites/').then((dirs) => {
// added a return here
return recursiveDirectorySearch(dirs, `${serverRoot}${siteName}/`);
})
.then(() => {
// everything is done at this point,
// serverPaths should be complete
})
.catch((err) => {
if (err) throw err;
});
function recursiveDirectorySearch(dirs, prevPath) {
let paths = dirs.filter((dir) => {
// returns directories only
return dir.type === 'd';
});
// added a return, Promise.all and changed forEach to map
return Promise.all(paths.map((path) => {
//added a return here
return server
.list(`${prevPath}${path.name}`)
.then((dirs) => {
console.log(`${prevPath}${path.name}`);
// swapped the next two lines
serverPaths.push(`${prevPath}${path.name}`);
// added a return here, push the path before
return recursiveDirectorySearch(dirs, `${prevPath}${path.name}`);
})
}));
}