node.js - Synchronous Call : Call 2nd function after 1st function is executed completely -
i stating coding in node.js , might simple question.
trying write xml parser/validator validate xml schema , values against values/ xpath stored in excel sheet.
now once validation function complete want call printresult function print final result. if try call function after first function .. printing variables initial values , if called within first iterating though number of xpaths present in excel sheet , printing result increments.
var mocha = require('mocha'); var assert = require('chai').assert; var fs = require('fs'); var parsestring = require('xml2js').parsestring; var xpath = require('xpath'); var dom = require('xmldom').domparser; var xlsx = require('xlsx'); var excel = require("exceljs"); var should = require('chai').should(); var hashmap = require('hashmap'); var colors = require('colors'); require('/xmlvalidator/dbconnect.js'); var map = new hashmap(); var elementmap = new hashmap(); var resultvalue; //console.log('hello'.green); map.set("pass", 0); map.set("fail", 0); map.set("invalid_path", 0); function computeresult(elementpath, result) { var pass = map.get("pass"); var fail = map.get("fail"); var invalidpath = map.get("invalid_path"); elementmap.set(elementpath, result); if (result == "pass") { pass++; map.set("pass", pass); } else if (result == "fail") { fail++; map.set("fail", fail); } else { invalidpath++; map.set("invalid_path", invalidpath) } printresult(); } function printresult() { var pass = map.get("pass"); var fail = map.get("fail"); var invalidpath = map.get("invalid_path"); console.log(("pass count :" + pass).green); console.log(("fail count :" + fail).red); console.log(("inavlid path :" + invalidpath).yellow); elementmap.foreach(function(value, key) { if (value == "invalid_path") console.log((key + ":" + value).yellow); else if (value == "fail") console.log((key + ":" + value).red); else console.log(key + ":" + value); }); } var workbook = new excel.workbook(); workbook.xlsx.readfile('utils/' + process.argv[2]) .then(function() { var worksheet = workbook.getworksheet(1); worksheet.eachrow(function(row, rownumber) { //console.log(rownumber); var row = worksheet.getrow(rownumber); var datapath1 = row.getcell("a").value; var datapath2 = row.getcell("b").value; var datapath = datapath1 + datapath2; //console.log(datapath); var datavalue = row.getcell("d").value; var flag = row.getcell("e").value; //console.log(flag) //console.log(datavalue); if (!flag) validate(datapath, datavalue, rownumber); //else console.log("not executed" + rownumber) }); }) function validate(datapath, datavalue, rownumber) { var fail = 0; fs.readfile('utils/' + process.argv[3], 'utf8', function(err, data) { if (err) { console.log("error error error error "); return console.log(err); } var doc = new dom().parsefromstring(data); var subid = string(xpath.select1(datapath, doc)); if (subid == "undefined") { /*console.log('undefined caught'); console.log("row number :" + rownumber);*/ var resultvalue = "invalid_path"; computeresult(datapath, resultvalue); } else { var subid = xpath.select1(datapath, doc); var value = subid.lastchild.data; /*console.log("row number :" + rownumber); console.log("actual value: " + value); console.log("expected value:" + datavalue );*/ if (datavalue == null) { assert.notequal(value, datavalue, "value not found"); resultvalue = "pass"; computeresult(datapath, resultvalue); } else { if (value == datavalue) resultvalue = "pass"; else resultvalue = "fail"; computeresult(datapath, resultvalue); } } }); } in code above want call printresult() function after validate function executed (workbook.xlsx.readfile)
can 1 please me out how use done () function or make sync call ?
if fs.readfileasync('utils/' + process.argv[3], 'utf8') can executed once, validate() synchronous , calling printresult() after verification loop trivial.
in main routine, can aggregate 2 promises ...
var promise1 = workbook.xlsx.readfile(); var promise2 = fs.readfileasync(); // requires `fs` promisified. ... before embarking on verification loop.
promise.all([promise1, promise2]).spread(/* verify here */); also whole bunch of tidying can considered, in particular :
- establishing "pass", "fail" , "invalid_path" constants avoid lots of repetitive string creation,
- using js plain objects in lieu of
hashmap, - building
mapelementmapinside print function. - having
validate()return result , buildingelementmapin main routine
here's whole thing, tight can it. may have made few assumptions not many bad ones ...
var mocha = require('mocha'); var assert = require('chai').assert; var promise = require("bluebird"); var fs = promise.promisifyall(require("fs")); // allow bluebird take pain out of promisification. var parsestring = require('xml2js').parsestring; var xpath = require('xpath'); var dom = require('xmldom').domparser; var xlsx = require('xlsx'); var excel = require("exceljs"); var should = require('chai').should(); // var hashmap = require('hashmap'); var colors = require('colors'); require('/xmlvalidator/dbconnect.js'); const pass = "pass"; const fail = "fail"; const invalid_path = "invalid_path"; function printresult(elementmap) { var key, result, map = { pass: 0, fail: 0, invalid_path: 0 }, colornames = { pass: 'black', fail: 'red', invalid_path: 'yellow' }; for(key in elementmap) { result = elementmap[key]; map[(result === pass || result === fail) ? result : invalid_path] += 1; console.log((key + ": " + result)[colornames[result] || 'black']); // presumably colors can applied associative syntax? if so, code can concise. } console.log(("pass count: " + map.pass)[colornames.pass]); console.log(("fail count: " + map.fail)[colornames.fail]); console.log(("inavlid path: " + map.invalid_path)[colornames.invalid_path]); } function validate(doc, datapath, datavalue) { var subid = xpath.select1(datapath, doc), value = subid.lastchild.data, result; if (string(subid) == "undefined") { result = invalid_path; } else { if (datavalue === null) { assert.notequal(value, datavalue, "value not found"); // not sure result = pass; } else { result = (value === datavalue) ? pass : fail; } } return result; } //main routine var workbook = new excel.workbook(); var promise1 = workbook.xlsx.readfile('utils/' + process.argv[2]); // question, workbook.xlsx.readfile() appears return promise. var promise2 = fs.readfileasync('utils/' + process.argv[3], 'utf8'); promise.all([promise1, promise2]).spread(function(data2, data3) { var worksheet = workbook.getworksheet(1), doc = new dom().parsefromstring(data3), elementmap = {}; worksheet.eachrow(function(row, rownumber) { // var row = worksheet.getrow(rownumber); // row formal variable ??? var datapath, datavalue; if (!row.getcell('e').value) datapath = row.getcell('a').value + row.getcell('b').value; datavalue = row.getcell('d').value; elementmap[datapath] = validate(doc, datapath, datavalue); }); printresult(elementmap); }); untested may not run @ least can raid code ideas.
Comments
Post a Comment