So I'm trying to nest my try/catch to make things run quicker and smoother.
Here's the original block which was outside (this was working):
try {
await page.waitFor("#login-form-os-captcha", { timeout: 1500 });
security = true
captcha = await new Promise( function (resolve, reject) {
prompt.get(['captcha'], function (err, result) {
console.log('Command-line input received:');
console.log(' captcha: ' + result.captcha);
if (result)
{
resolve(result.captcha);
}
else
{
reject("error with prompt captcha");
}
})
});
}
catch (e) {
security = false
}
Here's my attempt to nest that logic:
try
{
if (form)
{
await page.evaluate( (result) => {
document.querySelector("#login-form-username").value = 'user'
document.querySelector("#login-form-password").value = result.password // require password
try
{
let captcha_input = document.querySelector("#login-form-os-captcha")
if (captcha_input)
{
/* error here, Unexpected token new */
captch_input.value = await new Promise( function (resolve, reject) {
prompt.get(['captcha'], function (err, result) {
console.log('Command-line input received:');
console.log(' captcha: ' + result.captcha);
if (result)
{
resolve(result.captcha);
}
else
{
reject("error with prompt captcha");
}
})
});
}
}
catch (e)
{
console.log("captcha input error")
console.log(e);
}
document.querySelector("#login-form-submit").click()
}, result)
}
}
catch (e)
{
console.log("evaluate fail");
console.log(e);
process.exit(1);
}
Currently doing it this way, one after the other. Still not what I'm optimally looking for.
try
{
await page.waitFor("#login-form-username", { timeout: 3000 })
}
catch (e)
{
console.log("No page or waited too long")
process.exit(1);
}
// Check for captcha
try
{
await page.waitFor("#login-form-os-captcha", { timeout: 500 })
security = true
}
catch (e)
{
console.log("No captcha")
}
// Input captcha if there was a captcha
if (security)
{
try {
let captcha =
await new Promise( function (resolve, reject) {
prompt.get(['captcha'], function (err, result) {
console.log('Command-line input received:');
console.log(' captcha: ' + result.captcha);
if (result)
{
resolve(result.captcha);
}
else
{
reject("error with prompt captcha");
}
})
});
console.log("captcha", captcha)
await page.evaluate( (captcha) => {
document.querySelector("#login-form-os-captcha").value = captcha
}, captcha);
} catch (e) {
console.log("captcha error")
}
}
Update
Okay so it turns out to be a lack of async beforehand.
Related
I have the following API, the API is inserting into a table based on user selection from the client. User can select different material belonging to same experiment. In my payload, I have materials as array, experiment as string. I tried several ways to resolve my error. Following was the last try:
app.post("/insertMaterials", (req, res) => {
for (let mat of req.body["material"]) {
try {
oracledb.getConnection(
{
user: "some_user",
password: "some_pw",
connectString: "someConnStr",
},
function (err, connection) {
if (err) {
console.error("1" + err);
return;
}
connection.execute(
"INSERT INTO MATERIALS (ID, MAT_NAME, EXPR) VALUES((SELECT max(ID) + 1 FROM MATERIALS), :1, :2)",
[mat, req.body["experiment"]],
(err, result) => {
if (err) {
console.error("log " + err);
}
connection.commit();
connection.close();
}
);
}
);
} catch (error) {
console.log(error);
}
}
return res.status(200).json({
title: "SUCCESS: Materials Inserted",
});
});
I always get:
triggerUncaughtException(err, true / fromPromise /);
^
[Error: DPI-1002: invalid dpiConn handle] { errorNum: 0, offset: 0 }
Before I had a separate function of the block inside the for loop and I also tried with execeuteMany. Still same error. After trying lot other ways and reading in internet, I couldn't solve the issue. Except for finally catching uncaughtException and logging the error:
process.on('uncaughtException', (error, next) => {
let date = new Date()
errorLogStream.write(`Date: ${date}. Err: ${error.stack} \n`)
return
})
By catching this exception, my program does not break anymore and data is always inserted. But it would be great to know how and when this is raised and how this can be resolved or where if I am doing a mistake.
UPDATE
Payload example: {'material': ['F99999.7', 'J84845.4'], 'experiment': 'NA32R'}
Function:
async function addMatToExpr(exp, mat) {
let connection;
try {
connection = await oracledb.getConnection(
{
user: "some_user",
password: "some_pw",
connectString: "someConnStr",
});
result = await connection.execute("INSERT INTO MATERIALS (ID,
MAT_NAME, EXPR) VALUES((SELECT max(ID) + 1 FROM MATERIALS), :1, :2)",
[exp, mat], { autoCommit: true })
} catch (error) {
return res.status(404).json({
title: error,
});
} finally {
if (connection) {
try {
await connection.close()
} catch(error) {
console.log(error)
}
}
}
}
API:
app.post("/insertMaterials", (req, res) => {
for (let mat of req.body["materials"]) {
addMatToExpr(req.body["experiment"], mat)
}
});
Added the async/await function and the api that calls the function.
You need to 'await' the Oracle function calls so each completes before continuing. Currently the connection is being closed before the statement is executed.
See all the node-oracledb documentation and examples.
E.g.
async function run() {
let connection;
try {
connection = await oracledb.getConnection(dbConfig);
result = await connection.execute(sql, binds, options);
console.dir(result, { depth: null });
} catch (err) {
console.error(err);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err);
}
}
}
}
I am using node js function i have written the code long before but i need to add async and await in my functions i don know how to proceed with my code structure .
Here is my code structure
app.express.get('/api/member/logout', function (request, response) {
functionBal.logout(request.query.abc).then(function (result) {
if (result) {
response.set('Content-Type', 'application/json');
response.status(200);
response.json(result);
}
}).catch(function (err) {
response.set('Content-Type', 'application/json');
response.status(400);
response.json("Error -- " + err);
});
});
module.exports.log = function (abc) {
return new app.promise(function (resolve, reject) {
functionDal.log(abc).then(function (result) {
if (result)
resolve(result);
else {
reject("Error");
}
}).catch(function (err) {
reject(err);
});
})
};
module.exports.log = function (abc) {
return new app.promise(function (resolve, reject) {
mySqlConnection.connection().then(function (con) {
con.query("UPDATE member SET table1 = 0 WHERE abc = ?", [abc]).then(function (rows, fields) {
resolve('success');
}).catch(function (err) {
reject(err);
});
}).catch(function (err) {
reject(err);
});
});
}
Please help in adding async await in this coding structure
Give this is try.
app.express.get('/api/member/logout', async function (request, response) {
try {
let data = await functionBal.logout(request.query.abc)
response.set('Content-Type', 'application/json');
response.status(200);
response.json(result);
} catch (error) {
response.set('Content-Type', 'application/json');
response.status(400);
response.json("Error -- " + err);
}
});
module.exports.log = async function (abc) {
try {
return await functionDal.log(abc)
} catch (error) {
throw error
}
};
module.exports.log = async function (abc) {
try {
const con = await mySqlConnection.connection()
await con.query("UPDATE member SET table1 = 0 WHERE abc = ?", [abc])
return 'success'
} catch (error) {
throw error
}
}
Make sure, you have Node.js 8+.
I'm using "node-firebird" in my Firebird 2.5 project and I would like to use a single transaction for multiple inserts or update in some batches, but I couldn't use a global transaction. Could someone help me with this?
This is the single form in the official example:
Firebird.attach(options, function(err, db) {
if (err)
throw err;
// db = DATABASE
db.transaction(Firebird.ISOLATION_READ_COMMITED, function(err, transaction) {
transaction.query('INSERT INTO users VALUE(?,?)', [1, 'Janko'], function(err, result) {
if (err) {
transaction.rollback();
return;
}
transaction.commit(function(err) {
if (err)
transaction.rollback();
else
db.detach();
});
});
});
});
I trying this
const NewTransaction=()=>{
return new Promise((resolve, reject) => {
firebirdPool.get((err, db) => {
if (err) {
reject(err);
return;
}
DBGlobal=db;
DBGlobal.transaction(Firebird.ISOLATION_READ_COMMITED,
function(err, transaction) {
//here i trying save the transaction
TransactionGlobal=transaction;
if (err) {
reject(err);
return;
}
resolve(TransactionGlobal)
});
});//firebirdpool
});//promisse
}//function
const CommitTransaction=()=>{
return new Promise((resolve, reject) => {
TransactionGlobal.commit(function(err) {
if (err){
transaction.rollback();
reject(err);
return;
}
else {
DBGlobal.detach();
resolve(true);
}
});//transaction
});//promisse
}
const RollbackTransaction=()=>{
return new Promise((resolve, reject) => {
try{
TransactionGlobal.rollback();
resolve(true);
}
catch(err){
reject(err)
}
});//promisse
}
//usado com commit
const QueryExecTransaction = (sql,arrayparams=[]) => {
return new Promise((resolve, reject) => {
TransactionGlobal.query(sql,arrayparams,function(err, result) {
if (err) {
console.log('erro na execução da query');
TransactionGlobal.rollback();
reject(err);
return;
}
resolve(result);
return;
});//query
});//promisse
}
I run with this test
async function test(){
await NewTransaction();
console.log('Transacao Global',TransactionGlobal);
QueryExecTransaction(`insert into tabparametros(codigo,nome,valor) values (0,'teste1','')`);
CommitTransaction();
}
test();
But i received this error:
(node:9232) UnhandledPromiseRejectionWarning: Error: invalid transaction handle (expecting explicit transaction start)
I managed to solve, the alteration was in "commitretaining" and others small alters
below the code
//variaveis de "ambiente" salvas na raiz do projeto
//.env e .env.testing
require('dotenv').config({
path: (process.env.NODE_ENV === "test")||(process.env.NODE_ENV === "development") ? ".env.testing" : ".env"
})
var Firebird = require('node-firebird');
var fs = require('fs');
var options = {};
options.host = process.env.DB_HOST;
options.port = process.env.DB_PORT;
options.database = process.env.DB_DATABASE;
options.user = process.env.DB_USER;
options.password = process.env.DB_PASSWORD;
options.lowercase_keys = false; // set to true to lowercase keys
options.role = null; // default
options.pageSize = 4096; // default when creating database
//console.log(options);
//Conexao
// 5 = the number is count of opened sockets
var firebirdPool = Firebird.pool(5, options);
const NewTransaction=()=>{
return new Promise((resolve, reject) => {
firebirdPool.get((err, db) => {
if (err) {
reject(err);
return;
}
//aqui eu salvo o DB retornando
//DBGlobal=db;
db.transaction(Firebird.ISOLATION_READ_COMMITED,
function(err, transaction) {
//aqui eu salvo a transacao retornada
//TransactionGlobal=transaction;
if (err) {
reject(err);
return;
}
resolve({transaction,db});
});
});//firebirdpool
});//promisse
}//function
const CommitTransaction=(transaction,db)=>{
return new Promise((resolve, reject) => {
transaction.commitRetaining(function(err) {
if (err){
transaction.rollback();
reject(err);
return;
}
else {
db.detach();
resolve(true);
}
});//transaction
});//promisse
}
const RollbackTransaction=(transaction,db)=>{
return new Promise((resolve, reject) => {
try{
transaction.rollback();
db.detach();
resolve(true);
}
catch(err){
reject(err)
}
});//promisse
}
//usado com commit
const QueryExecTransaction = (transaction,sql,arrayparams=[]) => {
return new Promise((resolve, reject) => {
transaction.query(sql,arrayparams,function(err, result) {
if (err) {
console.log('erro na execução da query');
transaction.rollback();
reject(err);
return;
}
resolve(result);
return;
});//query
});//promisse
}
async function testa(){
const {transaction,db}=await NewTransaction();
//console.log('Transacao Global',transaction);
let psql='';
try{
for (let i=1;i<101;i++){
psql=`insert into tabparametros(codigo,nome,valor) values (0,'teste${i}-${new Date()}','')`
if (i==79){
//psql='forcando o erro';
}
await QueryExecTransaction(transaction,psql);
}
await CommitTransaction(transaction,db);
}
catch(e){
console.log('Erro no SQL');
console.log(e);
await RollbackTransaction(transaction,db);
}
console.log('Finalizado')
}
testa();
I am using node-async-loop for asyncronous programming
var array = ['item0', 'item1', 'item2'];
asyncLoop(array, function (item, next)
{
do.some.action(item, function (err)
{
if (err)
{
next(err);
return;
}
next();
});
}, function (err)
{
if (err)
{
console.error('Error: ' + err.message);
return;
}
console.log('Finished!');
});
Like this I am using three async loops one under one.
I want to send the response only after the third inner loop ends. How can I do so?.
Here is the link for node-async-loop (https://www.npmjs.com/package/node-async-loop)
here is my code which i writing but whnever i want to response when the last loop completes it say can set header after send to cliend.
also in console log i am getting data every time when data coming from query.
const id = req.params.id;
finalData = [];
tb_user.findOne({ where: { id: id } }).then((userRiverSys, err) => {
if (userRiverSys) {
// console.log(userRiverSys.regionJson)
asyncLoop(userRiverSys.regionJson, function (item, next) {
// console.log("item", item);
tb_riverSystems.findAll(
{
where: { regionId: item.id }
}).then((findriverSys, err) => {
if (err) {
next(err);
return;
}
// console.log("findriverSys", findriverSys);
if (findriverSys) {
asyncLoop(findriverSys, function (item1, next1) {
if (err) {
next(err);
return;
}
// console.log("item1", item1.dataValues);
tb_facilities.findAll(
{
where: { riverSystemId: item1.dataValues.id }
}).then((findFacilities) => {
if (findFacilities) {
// console.log("findFacilities", findFacilities[0].dataValues.name);
asyncLoop(findFacilities, function (item2, next2) {
if (err) {
next(err);
return;
}
tb_userAccess.findAll(
{
where: { facilityId: item2.dataValues.id }
}).then((userAccessFacilities, err) => {
// console.log("userAccessFacilities", userAccessFacilities[0].dataValues);
// var i = 0;
asyncLoop(userAccessFacilities, function (item3, next3) {
finalData.push({
UserId: item3.userid,
facilityId: item3.facilityId,
})
next3();
},
function (err) {
if (err) {
console.error('Error: ' + err.message);
return;
}
// i++;
// console.log('Finished!!!!');
// if (userAccessFacilities.length === i) {
// console.log("finalData", i);
// // res.json({"status":"true", "message":"update OrgChallenge"})
// }
})
return res.json({"status":"true", "message":"update OrgChallenge"})
// console.log("finalData", finalData);
})
next2();
}, function (err) {
if (err) {
console.error('Error: ' + err.message);
return;
}
console.log('Finished!!!');
});
}
});
next1();
}, function (err) {
if (err) {
console.error('Error: ' + err.message);
return;
}
console.log('Finished!!');
});
}
});
next();
}, function (err) {
if (err) {
console.error('Error: ' + err.message);
return;
}
console.log('Finished!');
});
} else {
console.log("err3", err)
}
})
If you promisify your asynchronous action (so it returns a promise), then you can just use a regular for loop and async/await and there is no need for a 3rd party library to sequence your asynchronous loop. This is modern Javascript:
const { promisify } = require('util');
do.some.actionP = promisify(do.some.action);
async function someFunction() {
const array = ['item0', 'item1', 'item2'];
for (let item of array) {
let result = await do.some.actionP(item);
// do something with result here
}
return someFinalResult;
}
someFunction().then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
FYI, in real code, many (or even most) asynchronous operations now offer promisified versions of their API already so usually you don't even need to do the promisify step any more. For example, pretty much all databases already offer a promise interface that you can just use directly.
const loop = async (arr, results = []) => {
const item = arr.shift()
if (!item) {
console.log("DONE");
return results;
}
// as async function
await new Promise(resolve => {
resolve(results.push(`asynced-${item}`))
})
return loop(arr, results);
}
(async () => {
const result = await loop(["item0", "item1", "item2"])
console.log(result);
})();
I'd be happy if I can help you.
but this script uses a recursive function instead of node-async-loop.
so this might not be suitable for you.
I have a typescript module.
public multipleQuery(queries: string[]) {
return new Promise(async (resolve, reject) => {
const cPool = new sql.ConnectionPool(this.room.db);
await cPool.connect().then((pool: any) => {
const transaction = new sql.Transaction(pool);
return transaction.begin(async (err: any) => {
const request = new sql.Request(transaction, { stream: true });
try {
queries.forEach(async (q) => {
await request.query(q);
});
transaction.commit((err2: any) => {
pool.close();
if (err2) {
reject(err2);
} else {
resolve(true);
}
});
} catch (err) {
transaction.rollback(() => {
pool.close();
reject(err);
});
}
});
}).catch((err: Error) => {
cPool.close();
reject(err);
});
});
}
queries variable is an array of string, I put inside a lot of sql insert queries.
No matter what I write in queries, I still receive this error, why?
RequestError: Requests can only be made in the LoggedIn state, not the
SentClientRequest state TransactionError: Can't acquire connection for
the request. There is another request in progress.
the solutions is to use async
const async = require("async");
public multipleQuery(queries: string[]) {
return new Promise((resolve, reject) => {
const pool = new sql.ConnectionPool(this.room.db);
return pool.connect().then((p: any) => {
const transaction = new sql.Transaction(p);
return transaction.begin((err: any) => {
const request = new sql.Request(transaction);
if (err) {
reject(err);
}
return async.eachSeries(queries, async (query: any, callback: any) => {
return request.query(query);
}, async (err2: any) => {
if ( err2 ) {
await transaction.rollback(() => {
pool.close();
reject(err2);
});
} else {
await transaction.commit(() => {
pool.close();
resolve(true);
});
}
});
});
});
});
}