在下面的代码中,我正在读取一些文件,并获取它们的文件名和文本。之后,我将数据存储在一个选项变量中以生成一个epub文件:
const Epub = require("epub-gen")
const folder = './files/'
const fs = require('fs')
let content = []
fs.readdir(folder, (err, files) => {
files.forEach(filename => {
const title = filename.split('.').slice(0, -1).join('.')
const data = fs.readFileSync(`${folder}${filename}`).toString('utf-8')
content.push({ title, data })
})
})
const option = {
title: "Alice's Adventures in Wonderland", // *Required, title of the book.
content
}
new Epub(option, "./text.epub")
问题是new Epub
在读取文件之前,content
准备就绪之前运行。我认为Promise.all
是这里的合适人选。我检查了Mozilla文档。但这显示了各种承诺,但我没有。因此,我不太确定如何在此处使用Promise.all
。
有什么建议吗?
答案 0 :(得分:2)
您的问题出在readdir
上,它是异步的,因此new Epub
就像您已经知道的那样,被称为 before ,它是callback
参数。
在readdirSync
之后,切换为使用const option ... new Epub...
或在callback
的{{1}}参数内移动readdir
。
答案 1 :(得分:1)
向数组添加promise。每个承诺都应以您推向content
当所有诺言都解决时,返回的值将是先前称为content
的数组。
此外,您可以并且应该使用所有异步fs
调用。因此readFileSync
可以替换为readFile
(异步)。但是,我没有用此异步调用替换您的代码,因此您可以清楚地看到回答原始问题所需的内容。
不确定我是否在代码段中正确嵌套了。
const Epub = require("epub-gen")
const folder = './files/'
const fs = require('fs')
let promises = []
fs.readdir(folder, (err, files) => {
files.forEach(filename => {
promises.push(new Promise((resolve, reject) => {
const title = filename.split('.').slice(0, -1).join('.')
const data = fs.readFile(`${folder}${filename}`).toString('utf-8')
resolve({
title,
data
})
}))
})
})
const option = {
title: "Alice's Adventures in Wonderland", // *Required, title of the book.
content
}
new Epub(option, "./text.epub")
Promise.all(promises).then((content) => {
//done
})
答案 2 :(得分:1)
由于您使用readFileSync,因此您现在可以同步进行所有操作。 因此,您可以将Epub创建的内容放置在forEach循环之后。
如果要异步,我的第一个问题是:
您的node.js版本是否支持util.promisify
(节点版本8.x或更高版本的iirc)?
如果是这样,则可以用来将诸如readFile之类的回调函数转换为Promise。如果没有,则可以使用相同的逻辑,但是可以像其他解决方案一样使用嵌套的回调。
const FS = require( 'fs' );
const { promisify } = require( 'util' );
const readFile = promisify( FS.readFile );
const readFolder = promisify( FS.readFolder );
readFolder( folder )
// extract the file paths. Maybe using `/${filename}` suffices here.
.then( files => files.map( filename => `${folder}${filename}`))
// map the paths with readFile so we get an array with promises.
.then( file_paths => file_paths.map( path => readFile( path )))
// fecth all the promises using Promise.all() .
.then( file_promises => Promise.all( file_promises ))
.then( data => {
// do something with the data array that is returned, like extracting the title.
// create the Epub objects by mapping the data values with their titles
})
// error handling.
.catch( err => console.error( err ));