[英]How to wait for internal promises to finish
我正在使用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)
在前者有機會循環通過之前Promise.all(theseItems)
解析。 我了解為什么會發生這種情況,並且我嘗試做一些事情,例如以Promise.resolve()的形式返回每個item
,等等,但是這些事情沒有用。
想知道我是否在用這種方法做一些天生的錯誤…
更新
我嘗試使用fsPromises
方法,但一直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)
})
承諾通過鏈接工作.then
調用( Promise.then(doStuff)
如果您許下諾言但又不做承諾,那么您將無法知道它何時完成。 為了鏈接來自內部函數的承諾,您必須返回承諾。
通常,您不想混合使用回調和Promise。
如果我要這樣做,我將只使用諾言。
const readdir = (target, options) =>
// returns a promise that resolves or rejects when the call finishes
new Promise((resolve, reject) =>
fs.readdir(target, options, (err, result) => {
if (err) reject(err);
resolve(result);
})
);
const collectSubPages = pages =>
// Wait for all the promises in the array to resolve
Promise.all(
// for each page, return a promise that resolves to the page/subpage object
pages.map(({ name }) =>
readdir(targetDir + "/" + name + "/publish", {
withFileTypes: true
})
.then(subpages => subpages.map(({ name }) => ({ name })))
.then(subpages => ({ name, subpages }))
)
);
readdir(targetDir, { withFileTypes: true })
.then(pages => collectSubPages(pages))
.then(console.log);
@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()
模式構造。 除非我有錯誤,否則應該給出相同的結果。
未經測試
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.