Jak*_*son 2 javascript recursion asynchronous node.js promise
我有一个库,可以扫描远程服务器上的文件目录。它返回一个像这样的 Promise:
client.scanRemoteDirectory(path)
.then(files => {
console.log(files)
})
Run Code Online (Sandbox Code Playgroud)
我也在尝试编写一个递归方法来扫描目录和子目录。但是我遇到了一些异步问题。我的功能是这样的:
const scanDir(path) {
// Scan the remote directory for files and sub-directories
return client.scanRemoteDirectory(path)
.then(files => {
for (const file of files) {
// If a sub-directory is found, scan it too
if (file.type === 'directory') {
return scanDir(file.path) // Recursive call
}
}
})
}
const scanDir('some/path')
.then(() => {
console.log('done')
})
Run Code Online (Sandbox Code Playgroud)
然而,这是有效的,因为return在scanDir()递归方法调用之前,这导致该方法仅扫描每个目录中的第一个子目录并跳过其余部分。
例如,如果结构是这样的:
/some/path
/some/path/dirA
/some/path/dirA/subdirA
/some/path/dirB
/some/path/dirB/subdirB
Run Code Online (Sandbox Code Playgroud)
上述方法只会扫描:
/some/path
/some/path/dirA
/some/path/subdirA
Run Code Online (Sandbox Code Playgroud)
dirB由于该方法dirA首先找到,它将跳过并且完全是孩子。
如果我只是return从return scanDir(...)呼叫中删除,那么它会很好地扫描所有内容。但是后来我的决赛console.log('done')发生得太快了,因为它是异步的。
那么我该如何解决这个问题呢?什么是正确的递归 Promise 方法,我仍然可以保留异步但也可以递归扫描每个子目录?
Promise.all在这种情况下,您可能希望使用并行运行您的“子”承诺,例如:
function scanDir(path) {
return client.scanRemoteDirectory(path)
.then(all => {
const files = all.where(file => file.type !== 'directory);
const dirs = all.where(file => file.type === 'directory);
return Promise.all(dirs.map(dir => scanDir(dir.path)) // Execute all 'sub' promises in parallel.
.then(subFiles => {
return files.concat(subFiles);
});
});
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用该reduce函数按顺序运行您的“子”承诺:
function scanDir(path) {
return client.scanRemoteDirectory(path)
.then(all => {
const files = all.where(file => file.type !== 'directory);
const dirs = all.where(file => file.type === 'directory);
return dirs.reduce((prevPromise, dir) => { // Execute all 'sub' promises in sequence.
return prevPromise.then(output => {
return scanDir(dir.path)
.then(files => {
return output.concat(files);
});
});
}, Promise.resolve(files));
});
}
Run Code Online (Sandbox Code Playgroud)
Async / await 绝对是最容易阅读的解决方案:
async function scanDir(path) {
const output = [];
const files = await client.scanRemoteDirectory(path);
for (const file of files) {
if (file.type !== 'directory') {
output.push(file);
continue;
}
const subFiles = await scanDir(file.path);
output = output.concat(subFiles);
}
return output;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
502 次 |
| 最近记录: |