node.js承诺在for循环中

时间:2018-05-21 15:32:56

标签: node.js pdf merge

我正在尝试合并多个文件(如果数据库结果返回带有非空'json'字段的多个元素,则创建PDF文档。)

现在合并只发生一次,并将第一个元素与element['json'] != ''合并在一起。

合并逻辑是:

  • 除了我们将创建的
  • 之外,所有PDF都已创建
  • 如果元素包含某些JSON,则创建PDF
  • 如果元素不包含JSON,请将其合并到以前的PDF
  • 也许将所有承诺推送到数组并将它们传递给Promise.all()会有帮助吗?真的卡住了。

    app.get("/api/generatePDF", jsonParser, function(req, res) {
    
    var saveFilename, savePath;
    var idDocument, idPatient, idDoctor, idItem;
    var orientation = "";
    var url = req.route.path;
    var tbl = "";
    var html = "";
    var hasTables = 0;
    console.log(req.query.json);
    var savedJSON = JSON.parse(req.query.json);
    var flag = 4;
    var id_inventory = parseInt(savedJSON['id_inventory']);
    var request = new sql.Request();
    var files = new Array();
    var badFiles = new Array();
    var options = "";
    var mergeNeeded = parseInt(savedJSON['param']);
    if (mergeNeeded == 1) {
        flag = 14;
    }
    var cnt = 0;
    var output = parseInt(savedJSON['output']);
    var mergedName = savedJSON['merged_name'];
    var numRows = 0;
    var idSpec = mergeNeeded;
    if (id_inventory == 0) {
        var pid = savedJSON['id_patient'];
        var idDocType = savedJSON['id_doc_type'];
        idSpec = savedJSON['id_spec'];
        flag = 10;
        request.input('id_patient', sql.Int, pid);
        request.input('id_doc_type', sql.Int, idDocType);
    }
    request.input('id_spec', sql.Int, idSpec);
    request.input('flag', sql.Int, flag);
    request.input('redo', sql.Int, 1);
    request.input('id_inventory', sql.Int, id_inventory);
    
    request.execute("create_json").then(function(result) {
        var size = result.recordset.length;
        return Promise.all(result.recordset.map(function(element) {
    
                savePath = element['path'];
                idItem = element['id_item'];
                saveFilename = element['filename'];
                options = { "format": "A4", "orientation": element['orientation'], "renderDelay": "undefined", "border": "10mm" }
                idPatient = element['id_patient'];
                htmlFile = element['id_template'];
                var fillTemplate = new Promise((resolve, reject) => {
                    files.push(basePath + element['path'] + separator + element['filename']);
                    if (element['json'] != "") {
                        fs.readFile('templates' + separator + element['id_template'] + '.html', 'utf8', function(err, data) {
                            if (err) {
                                return console.log(err);
                                reject(err);
                            }
                            html = data;
                           // filling the template
                            resolve(html);
                        });
                    }
                });
                var makeDirectory = new Promise((resolve, reject) => {
                    if (element['json'] != "") {
                        mkdirp(basePath + element['path'], function(err) {
                            if (err) {
                                reject(err);
                            }
                            resolve(element);
                        });
                    }
                });
    
                var makePDF = (html) => {
                    return new Promise((resolve, reject) => {
                        if (element['json'] != "") {
                            pdf.create(html, options).toFile(basePath + element['path'] + separator + element['filename'], function(err, res) {
                                if (err) {
                                    console.log(err);
                                    reject(err);
                                } else {                                   
                                    var request2 = new sql.Request();
                                    request2.input('flag', sql.Int, 5);
                                    request2.input('id_inventory', sql.Int, element['id_item']);
                                    request2.execute("PDF_create_json", (err2, result2) => {});                                    
                                }
    
                                if (mergeNeeded == 1) {
                                    if ((files.length > 100) || (files.length == size)) {
                                        PDFMerge(files, { output: basePath + mergedName }).then(() => {
                                            files.length = 0;
                                            files.push(basePath + mergedName);
                                            return "OK";
                                        })
                                    }
                                } resolve("OK");
                            });
                        } else {
    
                            if (mergeNeeded == 1) {
                                if ((files.length > 100) || (files.length == size)) {
                                    PDFMerge(files, { output: basePath + mergedName }).then(() => {
                                        files.length = 0;
                                        files.push(basePath + mergedName);
                                        return "OK";
                                    })
                                }
                                console.log("mergedname: " + mergedName);
                                console.log("Files have been merged");
                                resolve("OK");
                            }
                        }
    
                    });
                };
                return makeDirectory
                    .then(() => {
                        return fillTemplate
                    })
                    .then(makePDF)
                    .then(() => {
                        console.log(files);
                    })
            }
    
        ))
    }).then(results => {
        res.end("all done");
    })
    

    });

    1 个答案:

    答案 0 :(得分:1)

    您需要观察控制流程。是的,你正在创造承诺但不等待它们完成。您可以使用async/await同步或像bluebird

    这样的承诺库

    您的特定代码段的根本问题是result.recordset.forEach(element => {,它基本上是同步运行,然后调用res.end()

    您可以制作所有内容async/await,但您可能需要宣传request.execute("create_json", callback)电话。

    或者您可以使用Promise库来执行类似

    的操作
    Promise.each(result.recordset, function returnAPromise(){
      // your stuff here. Make sure this returns a Promise (chain)
    })
    .then(results => { 
      // now call res.end() 
    })
    

    确保首先处理数组中的所有内容。 (您还希望catch承诺链res.error()或任何呼叫,并确保您的Promise返回以便成功链接:

    return makeDirectory.then(() => {
                return fillTemplate.then(result => {
                    return makePDF(result).then(() => {
                         console.log("");
                    });
                });
            });
    

    或巩固

    return makeDirectory
    .then(() => {
       return fillTemplate
    })
    .then(makePDF)
    .then(() => { console.log('here') } )
    

    这些只是一个起点,但希望你觉得它有用。