node.jscouchdbcouchdb-nano

making node wait for db call to get completed


I just started writing node.js code.

I'm writing a code that extracts data from a pdf file, cleans it up and stores it in a database (using couchdb and accessing that using nano library).

The problem is that the calls are being made asynchronously... so the database get calls (i make some get calls to get a few affiliation files during the clean up) get completed only after the program runs resulting in variables being undefined. is there any way around this?

I've reproduced my code below

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);

Solution

  • This answer assumes you are using Node.js > v7.6

    Since db.view accepts a callback, and you wish to wait for it to finish, one solution will be to promisify it - meaning to turn it into a promise which can be awaited. You can use a library like Bluebird or you can even use Node's builtin promisify util. Then you can rewrite 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) {
    
        }
    }
    

    If you are not using Node.js > v7.6 (and cannot use async\await you can still utilize promises, by using their then method:

    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 => {});
    }
    

    Notice how the first then is returning something which is used in a later then.