javascript - 如何等待内部承诺完成
问题描述
我fs.readdir
用来获取目录列表,然后再次在回调中获取每个目录中的“子页面”列表。我希望第一个回调等到第二个回调完成,但我不知道该怎么做。
// Array to hold list of pages
const pageList = []
// Get contents of target directory (not recursive)
fs.readdir(targetDir, { withFileTypes: true }, (err, items) => {
// Stop and return if error
if (!!err) return err
// Go through found contents
const theseItems = items.map(item => {
const subpages = []
// Directory name
const dirName = item.name
// Set up published target for this directory
const thisTargetDir = targetDir + '/' + dirName + '/publish'
// Now get pages in the directory's published directory
// (assumes all files within subdirectories are .mdx pages to load)
return (
fs.readdir(thisTargetDir, { withFileTypes: true }, (err, pages) => {
const theseSubpages = pages.map(page => {
const mdxSuffix = /.mdx$/g
const pageName = page.name.replace(mdxSuffix, '')
return subpages.push({ name: pageName })
})
Promise.all(theseSubpages).then(() => {
// Add to page list array
pageList.push({ name: dirName, subpages: subpages })
})
})
)
})
Promise.all(theseItems).then(() => {
console.log('pageList at the end is: ')
console.log(pageList)
})
})
Promise.all(theseSubpages)
按预期工作,但在Promise.all(theseItems)
前者有机会循环之前解决。我理解为什么会发生这种情况,并且我尝试做一些事情,比如将每个都item
作为 Promise.resolve() 等返回,但是这些事情不起作用。
想知道我在这种方法中是否做错了什么……</p>
更新
我尝试使用该fsPromises
方法,但一直遇到相同的错误模式。最终使用node-dir包递归地遍历目录。下面的代码,并不是我想要做的事情的确切答案,但这得到了我正在寻找的结果。
const dir = require('node-dir')
const targetDir = __dirname + '/../pages/stuff'
const pageList = []
dir.paths(targetDir, (err, paths) => {
if (err) throw err
const baseMatch = __dirname.replace('/lib', '') + '/pages/stuff'
paths.dirs.map(dir => {
// Only publish paths
if (dir.substr(-7) === 'publish') {
// Get the slug directly before publish path
const contentSlug = dir.split('/').slice(-2)[0]
// Add this to main pageList array as top level objects
pageList.push({ name: contentSlug, subpages: [] })
}
})
paths.files.map(file => {
const filePathArray = file.split('/')
// Only publish paths
if (filePathArray.slice(-2)[0] === 'publish') {
// Get parent content slug for matching purposes
const parentContentSlug = filePathArray.slice(-3)[0]
// Get file name (remove .mdx suffix)
const mdxSuffix = /.mdx$/g
const fileName = filePathArray.slice(-1)[0].replace(mdxSuffix, '')
// Loop through main page list, find match, then add file as subpage
pageList.find((obj, key) => {
if (obj.name === parentContentSlug) {
return pageList[key].subpages.push({ name: fileName })
}
})
}
})
console.log('pageList at end:')
console.log(pageList)
})
解决方案
@David Yeiser,您自己的“更新”代码可以使用 Array 方法更简洁地编写.filter()
,.map()
以及各种优化,如下所示:
const dir = require('node-dir');
const targetDir = __dirname + '/../pages/stuff';
dir.paths(targetDir, (err, paths) => {
if (err) {
throw err;
}
const baseMatch = __dirname.replace('/lib', '') + '/pages/stuff';
const mdxSuffix = /.mdx$/g; // define once, use many times
const fileList = paths.files
.map(fileName => fileName.split('/'))
.filter(filePathArray => filePathArray[filePathArray.length - 2] === 'publish'); // Only 'publish' paths
const pageList = paths.dirs
.filter(dir => dir.substr(-7) === 'publish') // Only 'publish' paths
.map(dir => {
const name = dir.split('/').slice(-2)[0];
const subpages = fileList
.filter(filePathArray => filePathArray[filePathArray.length - 3] === name) // select those files whose "parent content slug" matches 'name'
.map(filePathArray => filePathArray[filePathArray.length - 1].replace(mdxSuffix, ''));
return { name, subpages };
});
console.log('pageList at end:');
console.log(pageList);
});
你会看到:
fileList
是用paths.files.map().filter()
模式构造的。pageList
是用paths.dirs.filter().map()
模式构造的。- 对于 中的每个条目
pageList
,subpages
都用一个fileList.filter().map()
模式构造。
除非我犯了错误,否则应该给出相同的结果。
未经测试
推荐阅读
- java - 无法写入 JSON:503 服务暂时不可用;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException
- php - PHP/MySQL 资源使用情况
- python - 在Python中增加矩阵的维数
- c# - 输入整数用户输入后继续程序c#
- android - 在 web 和 android 上开发调度应用程序的有效方法
- regex - 熊猫中的多个字符串清理
- javascript - Uncaught ReferenceError: jQuery is not defined VueJS Parcel
- java - 敌人渲染
- reactjs - 在多个屏幕上打开领域时反应原生错误
- java - BDX 中的 MeshAnim 动画