我编写了以下代码,使用html2pdf.js创建了多个pdf文件。后来我想将它们保存到档案中并下载所述档案。我正在使用jsZip创建并填充存档和fileSaver以保存它:
window.zip = new JSZip();
let masterDiv = document.createElement('div');
masterDiv.id = 'masterDiv';
document.body.appendChild(masterDiv);
// Stundenplan für jeden Kandidaten erstellen
for (let i = 0; i < window.allCandidates.length; i++) {
let candidate = window.allCandidates[i].split(',');
window.lastName = candidate[0];
window.firstName = candidate[1];
window.filter = 'candidate';
setScheduleView('masterDiv');
let worker = html2pdf();
let opt = {
margin: 1,
image: {
type: 'jpeg',
quality: 1
},
html2canvas: {
scale: 2
},
jsPDF: {
unit: 'mm',
format: 'A3',
orientation: 'portrait'
}
};
// PDF erstellen
worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
binary: true
});
});
setTimeout(() => {
clearDiv(masterDiv);
worker = null;
}, 50);
}
setTimeout(() => {
window.zip.generateAsync({
type: "blob"
}).then(function(content) {
saveAs(content, "allPDFs.zip");
});
}, 2000);
我的问题现在是:我得到的是一个包含完整内容的pdf,而不是每个循环一个pdf。我必须更改什么才能使html2pdf.js理解为每个循环创建一个新的pdf文件?
[您似乎没有正确地等待异步操作完成,特别是清除div的操作可能在生成pdf之前执行,而zip生成可能会发生同样的情况,根据您的方式,这里有几个选项要处理pdf:
与异步/等待一起使用:
// ...
async function generatePDFs(){
for (let cand of window.allCandidates) {
let candidate = cand.split(',');
// ...
// wait for every worker to finish before the next iterarion
await worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
binary: true
});
clearDiv(masterDiv);
});
}
window.zip.generateAsync({
type: "blob"
}).then(function (content) {
saveAs(content, "allPDFs.zip");
});
}
与reduce一起使用:,以防无法使用异步/等待
// create an array of functions so that each one of them will
// generate the pdf for a candidate and then clear the div.
let pdfGenerators = allCandidates.map((cand) => {
return () => {
let candidate = cand.split(',');
// ...
return worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
binary: true
});
clearDiv(masterDiv);
});
}
});
// call reduce on your pdf generators array starting from a resolved promise, so
// everytime a promise is resolved you enqueue the next one, after that generate the
// zip
pdfGenerators.reduce((pre, curr) => pre.then(curr), Promise.resolve()).then(() => {
window.zip.generateAsync({
type: "blob"
}).then(function (content) {
saveAs(content, "allPDFs.zip");
})
});
与Promise.all并行处理:对于这种方法(通常),停止使用全局变量,而是创建一个函数,该函数声明生成PDF时需要阅读的所有内容:
// ...
function generatePDF(candidate, i){
let div = document.createElement('div');
div.id = `candidate-${i}`;
document.body.append(div);
setScheduleView(div.id);
let [lastName, firstName] = candidate.split(',');
// ...
return worker.set(opt).from(div).outputPdf().then((pdf) => {
window.zip.file(lastName + '.' + firstName + '.pdf', pdf, {
binary: true
});
clearDiv(div);
});
}
// wait for all pdfs to be generated (in parallel)
Promise.all(allCandidates.map(generatePDF)).then(() => {
window.zip.generateAsync({
type: "blob"
}).then(function (content) {
saveAs(content, "allPDFs.zip");
});
});
为了正确处理JS中的异步编程,请正确阅读Promises和Async functions。