galeej
galeej

Reputation: 563

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:[email protected]');



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

Upvotes: 1

Views: 7455

Answers (2)

OzW
OzW

Reputation: 858

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.

Upvotes: 2

Henry Woody
Henry Woody

Reputation: 15662

To make Node run asynchronously, you can use the keywords async and await. They work like this:

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

It's pretty simple in Node to get functions to execute asynchronously. Just put the async keyword at the beginning of the function definition and then put await in front of anything that you want to block execution until completed.

Upvotes: 1

Related Questions