首页 > 解决方案 > 如何等待内部承诺完成

问题描述

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)
})

标签: javascriptnode.jspromise

解决方案


@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()模式构造的。
  • 对于 中的每个条目pageListsubpages都用一个fileList.filter().map()模式构造。

除非我犯了错误,否则应该给出相同的结果。

未经测试


推荐阅读