有个需求场景是须要把某个目录下的全部指定文件的内容生成pdf,由于是前端开发,因此就用node来干活
首先是pdf的包是用pdfkit, 这里有两个坑,第一个是生成的文件中可能会有系统没法识别的换行和空格,会被替换成莫名其妙的符号,所以在拼接完内容后,要使用 str.replace(/rn|r/g, 'n')
进行过滤,第二个坑是中文字符会乱码,所以要引入中文ttf,例如
doc.font('./msyh.ttf') ;
接下来是获取全部文件内容,在一开始我是判断文件的长度来识别是否结束,可是文件获取是异步,递归的时候同时进行这么多读取操做,如何才能判断全部异步操做都已经结束了呢,答案就是咱们的Promise.all啦
首先咱们将fs模块的几个要用到方法promiseify化,也就是咱们能够将异步操做包装在promise函数中,因为文件操做的回调函数也是做为参数传入(万能的JS),因此咱们只要获取到arguments中的callback函数,而且根据成功或者失败去resolve或reject就行啦,
那么Promise.all是用来干吗呢?
Promise.all 接收一个 promise 对象的数组做为参数,当这个数组里的全部 promise 对象所有变为resolve或 有 reject 状态出现的时候,它才会去调用 .then 方法,它们是并发执行的。也就是说咱们并行执行的全部文件读取操做,能够用Promise.all来解决啦!前端
const fs = require('fs') const yargs = require('yargs') const PDF = require('pdfkit') const readdir = promisify(fs.readdir); const stat = promisify(fs.stat); const readFile = promisify(fs.readFile); const doc = new PDF(); function uuid(times = 10) { let g = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', str = ''; let len = g.length; for (let i = 0; i < times; i++) { str += g[Math.round((Math.random() * (len - 1)))]; } return str; } let { path = '', name = uuid(), fileType = '' } = yargs.argv || {}; let str = ''; fileType = (fileType.split(',') || []).filter(item => item !== '') function promisify(fn) { return function() { let args = Array.from(arguments); return new Promise(function(resolve, reject) { args.push(function(err, result) { if (err) { reject(err); } else { resolve(result); } }); fn.apply(null, args); }); } } function readDirRecur(file, callback) { return readdir(file).then(function(files) { files = files.map(function(filename) { let fullPath = `${file}/${filename}`; return stat(fullPath).then(function(stats) { let limmit = fileType.length ? fileType.find(item => filename.includes(`.${item}`)) : true; if (stats.isDirectory()) { return readDirRecur(fullPath, callback); } else if (limmit) { return readFile(fullPath, 'utf8').then(function(data) { callback(filename, data, fullPath); }); } }) }); return Promise.all(files); }); } if (!path) return false; readDirRecur(path, function(filename, data, fullPath) { str += data; }).then(function() { str = str.replace(/\r\n|\r/g, '\n'); doc.pipe(fs.createWriteStream(`${name}.pdf`)) doc.fontSize(10); doc.font('./msyh.ttf'); doc.text(str, 50, 50); doc.end() }).catch(function(err) { console.log(err); });