使节点等待数据库调用完成

making node wait for db call to get completed

我刚开始写 node.js 代码。

我正在编写一个代码,从 pdf 文件中提取数据,清理它并将其存储在数据库中(使用 couchdb 并使用 nano 库访问它)。

问题是调用是异步进行的...所以数据库 get 调用(我在清理期间进行了一些 get 调用以获取一些从属文件)仅在程序运行后才会完成导致变量未定义。有什么解决办法吗?

我在下面复制了我的代码

const fs = require('fs');

const os = require('os');

var couchDB = require('couch-db').CouchDB;

var pdf_table_extractor = require('pdf-table-extractor');

const filename = "PQ-PRI-0005-1806-01-0000_quoteSlipForLIBVIDGI1.pdf"

var nano = require('nano')('https://couchadmin:difficulttoguessmypassword@dbdev.perilwise.com');



var server = new couchDB('https://db.url.com');

server.auth("admin","admin");

var db = nano.db.use('pwfb');

var temp = [];

//New callView function
async function callView(){
try{

    const doc = await view('liabilitymdm','pi');
    for (var i =0; i<doc.rows.length;i++){
        tmp.push(doc.rows[i]);
    };
    return doc;
} catch(e){
    console.log(e);
};

};

function suc(result){
    let ttmp = [];
    console.log(result);
    var pageTables = result.pageTables;
    var firstPageTables = pageTables[0].tables;
    ttmp = callView();
    //this console log shows Promise { <pending> }
    console.log(ttmp)
    for (var k = 0; k < firstPageTables.length; k++) {
     var temp = firstPageTables[k];
     if (temp.length > 0) {
      dump.push(temp);
        }
    }
    // console.log(dump);
    var insurer = filename.substr(37,8);
    read_quote_slip(insurer,dump);
}


var read_quote_slip = (insurer,data) => {
    console.log("read_quote_slip correctly entered");
    var finOut = {};
    if (insurer === "LIBVIDGI"){
        finOut.insurer = insurer;
        finOut.policyType = data[2][0].replace(/Quotation  for/g,"");
        finOut.natureOfWork = data[13][3];
        let dedpos = indexGetter(data, "Deductible")[0];
        finOut.deductible = data[dedpos+1][0];
        let cov = indexGetter(data, "Coverage Territory and Jurisdiction")[0];
        finOut.coverageTerritory = data[cov+1][0].replace(/Territory/g,"");
        finOut.coverageJurisdiction = data[cov+2][0].replace(/Jurisdiction/g,"");
        let ext = indexGetter(data,"Extensions")[0];
        finOut.coverage = data[ext+1][0].split(/\r?\n/);
        let majexc = indexGetter(data,"Major Exclusions")[0];
        finOut.exclusions = data[majexc+1][0].split(/\r?\n/);
        let prdtl = indexGetter(data,"Description")[0];
        let prm = premiumcompute(data,prdtl,dedpos);
        finOut.premium = prm;
        finCleaned = libvidgi_cleaned(finOut);
        // console.log(finCleaned);
    }
}

var indexGetter = (words,toFind) => {
    var finindex = [];
    for (var i = 0; i < words.length; i++){
        for (var j = 0; j < words[i].length; j++){
            if(words[i][j].indexOf(toFind) >=0 ){
                finindex.push(i);

    }
  }
}
    return finindex;
}


var premiumcompute = (data, from, to) => {
    let finprem = [];
    let numbop = to - from - 2;
    let incr = 0;
    for (var i = from+2; i < to; i++){
        let pr = {};
        pr.option = incr+1;
        pr.sumInsured = data[i][2].replace(/ /g,"");
        pr.premium = data[i][data[i].length - 1].replace(/ /g,"");
        finprem.push(pr);
        incr +=1;
    }
    return finprem;
}


var libvidgi_cleaned = (finOut) => {

    return finOut;

}

var fal = (result) => {
    console.log(result);
    console.log("there was an error");
}


var readPDFFile = function(filename){
    //Decide which insurer from the filename
    // console.log(filename);
    console.log(filename.substr(37,8)+"Printed on line 38");
    insurer = filename.substr(37,8)
    pdf_table_extractor(filename, (result) => {suc(result)} , fal);

    }



var libvidgi_data_extract = (data) => {
    console.log(data);
    let arr = data.pageTables.tables;
    for (var i = 0; i <= arr.length; i++ ){
        console.log(arr[i]);
    }
}

readPDFFile(filename);

要使Node运行异步,可以使用关键字asyncawait。 他们是这样工作的:

async function doSomething () {
    const formattedData = formatData();
    const result = await db.postToDatabase(formattedData);
    // the below will not happen until the above line is finished
    doSomethingElse(result);
}

在 Node 中让函数异步执行非常简单。只需将 async 关键字放在函数定义的开头,然后将 await 放在您想要阻止执行直到完成的任何内容前面。

此答案假定您使用的是 Node.js > v7.6

由于 db.view 接受回调,而您希望等待它完成,一个解决方案是 promisify 它 - 意思是将它变成 promise 可以是 awaited。您可以使用像 Bluebird or you can even use Node's builtin promisify util 这样的库。然后你可以改写 callViews:

const {promisify} = require('util');

const view = promisify(db.view);

async function callView() {
    try {
        const doc = await view('liabilitymdm', 'pi');
        // the async operation is now guaranteed to be done
        // (if there is an error it will be caught by the catch clause)
        for (var i = 0; i < doc.rows.length; i++) {
            temp.push(doc.rows[i]);
        }
        console.log(temp);
    } catch (e) {

    }
}

如果你没有使用 Node.js > v7.6(并且不能使用 async\await 你仍然可以使用 promise,通过使用他们的 then方法:

const {promisify} = require('util');

const view = promisify(db.view);

function callView() {
    view('liabilitymdm', 'pi')
        .then(doc => {
            for (var i = 0; i < doc.rows.length; i++) {
                temp.push(doc.rows[i]);
            }
            console.log(temp);
            return temp;
        })
        .then(temp => {
            console.log(temp);
        })
        .catch(e => {});
}

注意第一个 then 是如何返回在后面的 then 中使用的东西的。