.then()似乎没有在等待上一个.then()

时间:2019-05-21 20:54:00

标签: javascript asynchronous fs-extra

我正在创建一个将多个markdown文件转换为一个pdf的过程。它为在源目录中找到的每个.md文件创建一个pdf文件。然后将各个pdf文件合并为一个pdf。正是这最后一步未能说明单个pdf文件不存在。

const markdownpdf = require('markdown-pdf')
const path = require('path')
const PDFMerge = require('pdf-merge')
const fse = require('fs-extra')

const srcDir = '../manuscript'
const outDir = 'out'

const main = () => {

    fse.pathExists(outDir)
    .then(() => {
      fse.remove(outDir).then(() => {
        fse.ensureDir(outDir)
      }).then(() => {
        return fse.readdir(srcDir)
      }).then((srcDirFiles) => {
        console.log('source directory file count = ', srcDirFiles.length)
        return srcDirFiles.filter(f => path.extname(f) === '.md')
      }).then((mdFiles) => {
        console.log('number of md files', mdFiles.length);
        return mdFiles.map(file => {

          const outFileName = `${path.basename(file, '.md')}.pdf`
          fse.createReadStream(`${srcDir}/${file}`)
            .pipe(markdownpdf())
            .pipe(fse.createWriteStream(`${outDir}/${outFileName}`))
          return `${outDir}/${outFileName}`
        })
      }).then(outFiles => {
        console.log('number of pdf files created =', outFiles.length)
        PDFMerge(outFiles, { output: `${__dirname}/3.pdf`  })
      })
    })
}

main()

如果我将PDFMerge()行包装到setTimeout()中,它将起作用

setTimeout(() => {
  PDFMerge(outFiles, { output: `${__dirname}/3.pdf` })
}, 1000)

我想知道为什么需要setTimeout()以及需要更改什么,所以不需要。

我还编写了一个异步/等待版本,该版本也存在同样的问题,并且还可以使用setTimeOut()

修改

为响应Zach Holt的建议,以下是async / await版本:

const markdownpdf = require('markdown-pdf')
const path = require('path')
const PDFMerge = require('pdf-merge')
const fse = require('fs-extra')

const srcDir = '../manuscript'
const outDir = 'out'

const createPdf = async (file) => {
  try {
    const outFileName = `${path.basename(file, '.md')}.pdf`
    await fse.createReadStream(`${srcDir}/${file}`)
      .pipe(markdownpdf())
      .pipe(await fse.createWriteStream(`${outDir}/${outFileName}`))
  }
  catch (e) {
    console.log(e)
  }
}

const makePdfFiles = (files) => {
  files.forEach(file => {
    if (path.extname(file) === '.md') {
      createPdf(file)
    }
  })
}

const mergeFiles = async (files) => {
  try {
    await PDFMerge(files, {output: `${__dirname}/3.pdf`})
  }
  catch (e) {
    console.log(e)

  }
}

const addPathToPdfFiles = (files) => {
  return files.map(file => {
    return `${outDir}/${file}`
  })
}

const main = async () => {
  try {
    const exists = await fse.pathExists(outDir)
    if (exists) {
      await fse.remove(outDir)
    }
    await fse.ensureDir(outDir)
    const mdFiles = await fse.readdir(srcDir)
    const filesMade = await makePdfFiles(mdFiles)
    const pdfFiles = await fse.readdir(outDir)
    const pdfFilesWithPath = addPathToPdfFiles(pdfFiles)
    mergeFiles(pdfFilesWithPath)
    // setTimeout(() => {
    //   mergeFiles(pdfFilesWithPath)
    // }, 1000)
  } catch (e) {
    console.log(e)
  }
}

它有同样的问题。

我也尝试过:

const makePdfFiles = files => {
  return new Promise((resolve, reject) => {
    try {
      files.forEach(file => {
        if (path.extname(file) === '.md') {
          createPdf(file)
        }
      })
      resolve(true)
    } catch (e) {
      reject(false)
      console.log('makePdfFiles ERROR', e)
    }
  })
}

但这没什么区别。

4 个答案:

答案 0 :(得分:2)

您需要从ensureDir()退回承诺,以使其等待。

答案 1 :(得分:1)

我认为问题可能在于,您正在为每个.md文件创建一个读取流,但没有等待读取完成再尝试合并outFiles。

您可能会等到outFiles的长度等于合并之前找到的md个文件的数量。

此外,您应该为此坚持异步/等待。它将使代码更加清晰

答案 2 :(得分:1)

让我过分简化您的代码以说明问题:

Navigation.push('Player')

与以下相同:

p1.then(() => {
  p2.then().then().then()
}).then(/* ??? */)


链接所需的是返回内部的承诺

p1.then(() => {
  p2.then().then().then()
  return undefined
}).then(/* undefined */)

与以下相同:

p1.then(() => // no {code block} here, just return value
  p2.then().then().then()
).then(/* ??? */)

答案 3 :(得分:0)

据我所知,最初的问题是方法,而不是其他人正确指出的明显错误。我找到了一个从多个md文件生成一个pdf的总体目标的简单得多的解决方案。

const markdownpdf = require('markdown-pdf')
const path = require('path')
const fse = require('fs-extra')

const srcDir = '../manuscript'

const filterAndAddPath = (files) => {
  try {
    const mdFiles = files
      .filter(f => path.extname(f) === '.md')
      .map(f => `${srcDir}/${f}`)
    return mdFiles
  }
  catch (e) {
    console.log('filterAndAddPath', e)

  }
}

const main4 = async ()  => {
  const allFiles = await fse.readdir(srcDir)
  const mdFiles = filterAndAddPath(allFiles)
  const bookPath = 'book.pdf'
  markdownpdf()
    .concat.from(mdFiles)
    .to(bookPath, function() {
      console.log('Created', bookPath)
    })
}

main4()