有一个需求场景,需要将某个目录下所有指定文件的内容生成pdf。因为是前端开发,所以用node来干活。首先,pdf包使用pdfkit。这里有两个坑,第一个生成的文件中可能会有系统无法识别的换行和空格,会被替换成莫名其妙的符号,所以拼接内容后,使用str.replace(/rn|r/g,'n')来过滤,第二个坑是汉字会乱码,所以需要引入中文ttf,比如doc.font('./msyh.ttf');下一步是获取文件的所有内容。一开始我判断文件长度来判断是否结束,但是文件获取是异步的,那么递归的时候同时进行了那么多读操作,怎么判断所有异步操作都结束了呢?答案是我们的Promise.all。首先,我们将使用几个fs模块来使方法promiseify,即我们可以将异步操作包装在promise函数中。由于文件操作的回调函数也是作为参数传入的(通用JS),我们只需要在arguments中获取回调函数,并根据success或者失败resolve或者reject即可,那什么是Promise.all用来做什么?Promise.all接收一组promise对象作为参数。当数组中的所有promise对象都已解决或具有拒绝状态时,它将调用并发执行的.then方法。也就是说,我们所有并行执行的文件读取操作,都可以用Promise.all来解决!constfs=require('fs')constyargs=require('yargs')constPDF=require('pdfkit')constreaddir=promisify(fs.readdir);conststat=promisify(fs.stat);constreadFile=promisify(fs.readFile);constdoc=newPDF();functionuuid(times=10){letg='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',str='';让len=g.length;for(leti=0;iitem!=='')functionpromisify(fn){returnfunction(){让args=Array.from(参数);returnnewPromise(function(resolve,reject){args.push(function(err,result){if(err){reject(err);}else{resolve(result);}});fn.apply(null,参数);});}}functionreadDirRecur(file,callback){returnreaddir(file).then(function(files){files=files.map(function(filename){letfullPath=`${file}/${filename}`;返回stat(fullPath).then(function(stats){letlimmit=fileType.length?fileType.find(item=>filename.includes(`.${item}`)):true;如果(stats.isDirectory()){返回readDirRecur(fullPath,回调);}elseif(limmit){returnreadFile(fullPath,'utf8').then(function(data){callback(filename,data,fullPath);});}})});返回Promise.all(文件);});}if(!path)returnfalse;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);});