循环中Logger.log重复打印同一值的问题排查与最佳实践咨询
问题描述
使用以下Google Apps Script将指定文件夹中的Google文档转存为PDF时,发现Logger.log打印的文件名始终固定为某一个随机值,不会随迭代处理的文档变化。代码如下:
//https://github.com/Davor111/google-docs-to-pdf/blob/master/app.js function gdocToPDF() { // Replace this ID var documentRootFolder = DriveApp.getFolderById("***redacted***") // replace this with the ID of the folder that contains the documents you want to convert Logger.log("Downloading " + documentRootFolder.getName() + "..."); var pdfFolder = DriveApp.getFolderById("***redacted***"); // replace this with the ID of the folder that the PDFs should be put in. var documentRootFiles = documentRootFolder.getFiles() while(documentRootFiles.hasNext()) { createPDF(documentRootFiles.next().getId(), pdfFolder.getId(), function (fileID, folderID) { if (fileID) createPDFfile(fileID, folderID); }) } } function createPDF(fileID, folderID, callback) { var templateFile = DriveApp.getFileById(fileID); var templateName = templateFile.getName(); var existingPDFs = DriveApp.getFolderById(folderID).getFiles(); //in case no files exist if (!existingPDFs.hasNext()) { return callback(fileID, folderID); } for (; existingPDFs.hasNext();) { var existingPDFfile = existingPDFs.next(); var existingPDFfileName = existingPDFfile.getName(); if (existingPDFfileName == templateName + ".pdf") { Logger.log("PDF exists already. No PDF created") return callback(); } if (!existingPDFs.hasNext()) { Logger.log(existingPDFfileName + " created") return callback(fileID, folderID) } } } function createPDFfile(fileID, folderID) { var templateFile = DriveApp.getFileById(fileID); var folder = DriveApp.getFolderById(folderID); var theBlob = templateFile.getBlob().getAs('application/pdf'); var newPDFFile = folder.createFile(theBlob); newPDFFile.setName(templateFile.getName() + '.pdf'); }
迭代逻辑的核心误区
- 日志打印对象错误:
createPDF函数中,当确认需要生成新PDF时,日志打印的是existingPDFfileName(最后一个遍历到的已存在PDF文件名),而非当前待转换的文档名templateName,导致无论处理哪个文档,只要无重复就会打印同一个已存在PDF的名字,造成“文件名未变化”的错觉。 - 存在性检查逻辑漏洞:仅当遍历完所有已存在PDF且最后一个PDF不匹配时,才触发PDF生成回调。逻辑冗余且易出错——比如只要文件夹里的最后一个PDF不匹配就生成,而非只要没有匹配的目标PDF就生成。
- 冗余的回调设计:当前场景是完全同步的文件处理流程,引入回调不仅增加了代码复杂度,还可能引发变量作用域相关的潜在问题。
最佳实践方案
- 简化同步逻辑,移除不必要的回调:将存在性检查与PDF生成合并为线性流程,避免回调带来的复杂度。
- 高效的存在性检查:使用DriveApp的
searchFiles方法直接按文件名搜索目标PDF,无需遍历所有文件,提升效率且代码更简洁。 - 精准日志输出:打印当前处理的文档名或目标PDF名,确保日志能准确反映处理进度。
- 过滤文件类型:仅处理Google Docs类型的文件,避免误处理其他格式文件。
修正后的代码
function gdocToPDF() { const sourceFolderId = "***redacted***"; // 替换为源文件夹ID const targetFolderId = "***redacted***"; // 替换为PDF存放文件夹ID const sourceFolder = DriveApp.getFolderById(sourceFolderId); const targetFolder = DriveApp.getFolderById(targetFolderId); Logger.log("开始处理文件夹: " + sourceFolder.getName()); // 仅遍历Google Docs类型文件 const docFiles = sourceFolder.getFilesByType(MimeType.GOOGLE_DOCS); while (docFiles.hasNext()) { const currentDoc = docFiles.next(); const docName = currentDoc.getName(); const targetPdfName = `${docName}.pdf`; // 直接搜索目标PDF是否存在 const existingPdfQuery = `title='${targetPdfName}'`; const existingPdfs = targetFolder.searchFiles(existingPdfQuery); if (existingPdfs.hasNext()) { Logger.log(`跳过:${targetPdfName} 已存在`); continue; } // 生成并保存PDF const pdfBlob = currentDoc.getBlob().getAs('application/pdf'); const newPdfFile = targetFolder.createFile(pdfBlob); newPdfFile.setName(targetPdfName); Logger.log(`已生成:${targetPdfName}`); } }
内容的提问来源于stack exchange,提问作者MrCamilleri
相关产品推荐
相关产品推荐

