I am here because i am having troubles debugging my app. It's very annoying not see why my app crashes. I was using promises (with then/catch blocks) but i get on the necessity of using async/await.
I have a method where i do multiple await on it. The problem here is that if my app crashes because any reason i never know whats the problem on it. I have described the block like this:
static async processCSGOGroupsAndUsers (groupName) {
try{
const csgoApiData = await csgoApi(groupName);
const parsedData = await xmltojson(csgoApiData);
const id = parsedData.memberList.groupID64;
//const members = await retrieveMembers(groupName, parsedData.memberList.memberCount);
const totalUsers = await UsersService.processCSGOUsers(id, parsedData);
const csgoGroup = {
name: parsedData.memberList.groupDetails.groupName,
siteUrl: parsedData.memberList.groupDetails.groupURL,
id,
totalUsers
};
await GroupsDao.save(csgoGroup);
}catch (err){
return err;
}
}
static async processCSGOUsers (groupId, parsedData) {
try{
let steamIdsArr = [];
const usersSteamIdsObj = parsedData.memberList.members.steamID64;
Object.keys(usersSteamIdsObj).forEach(key => {
//if (steamIdsArr.length < 2) // TODO csGOBackPackAPI don't let me do more than 50 request per hour
steamIdsArr.push({
steam_group_id_64: groupId,
steam_id_64: usersSteamIdsObj[key]
});
});
//const filteredUsers = await UserService.filterUsersByInventoryValue(steamIdsArr);
UsersDao.saveUsers(steamIdsArr);
} catch(err){
console.log(err);
return err;
}
}
static processCSGOGroups(req, res){
GroupService
.processCSGOGroupsAndUsers(req.body.group)
.then( () => res.status(200).end())
.catch( error => res.status(400).send(error));
}
Is there a better approach than mine's?
I created an NPM package to help with situations like this.
https://www.npmjs.com/package/#simmo/task
The following shows example usage. The idea is that it should help remove try/catch replacing with conditional logic - hopefully helping to make everything a little more readable! :)
import task from '#simmo/task'
const { error, data } = await task(fetch('/some-api'))
if (error) {
// Failure
console.error(error)
} else {
// Success
console.log(data)
}
Related
I'm a newbie studying coding.
I tried to mock mysql database query, so I followed below code(https://techhelpnotes.com/node-js-mock-database-jest-using-ts-jest-utils/)
//database.js
const getDbConnection = () => {
const pool = mysql.createPool(DB_CONFIG);
return {
query : function (sql) {
return util.promisify(pool.query).call(pool, sql);
};
//controller.js
try {
let result = await db.query(sql);
res.status(200).json(result);
} catch (error) {
console.log(DB error, error);
}
It worked for me, but I thought I could return the query with await by using it in databse.js like the one below
query : async function(sql) {
try {
return await util.promisify(pool.query).call(pool, sql);
} catch (error) {
console.log(DB error, error);
}
}
so I thought I can use query function without error handling
let result = await db.query(sql);
But it doesn't work. What difference is there between the two codes that makes the above code work and the below now??
Many thanks!
With regards to my Azure function, I cannot for the life of me figure out why I'm getting MongoExpiredSessionError: Cannot use a session that has ended error when trying to do an extremely simple insertion. I've tried JSON.parse(result); and JSON.stringify(result); but still getting the same error.
I've also tried removing the finally block, tried adding await in front of collection() but still getting the same error. I've pretty much done all the I can that I've found on the web to troubleshoot but to no avail.
What am I doing wrong?
Here's my code:
const mongo = require('mongodb');
const MongoClient = require('mongodb').MongoClient;
const uri = "myUri"
module.exports = async function (context, req) {
const client = await MongoClient.connect(uri, {useNewUrlParser:true}).catch(err => {context.log(err); });
let result = null;
let callerEntityProfile = req.body.CallerEntityProfile;
let packIdInput = callerEntityProfile.Entity.PackIdInput;
let userId = callerEntityProfile.Entity.UserID;
try {
const db = await client.db("myDB");
let collection = await db.collection("myCollection");
let query = { userId : userId };
result = await collection.findOne(query);
let insertPack = {
"PackId" : packIdInput
};
result.packsOwned.push(insertPack);
JSON.parse(result);
collection.insertOne(result, function(err, r) {
console.log('inside insertOne')
console.log(err); // this is where it's showing the error message
});
}
catch (err) {
context.log(err);
}
finally {
client.close();
}
}
Since it does not wait until the end of the asynchronous function, the close action is faster than insertMany action. You can try the following:
const DB = client.db(databasename);
const myAsyncFunction = async() => {
const collection = await DB.collection(nameofcollection); // do this INSIDE async function
await collection.insertMany(details); // similarly inside async
};
client.close();
Alternatively, you may try something like this:
client.connect(err => {
if(err) return console.log(err);
client.db(databasename).collection(nameofcollection)
.then(collection => collection.insertMany(details))
.then(() => client.close());
});
You can refer to these similar SO threads -
How to fix MongoError: Cannot use a session that has ended
MongoError: Cannot use a session that has ended
Node js throws MongoError
MongoError
I'm querying a postgres db using async-await method.
export const queryByJobCode = async (jobCode) => {
try {
const text = 'select ...';
const values = [jobCode];
const jobCodeData = await dbConnectorUtil.pool.query(text, values);
return jobCodeData.rows;
} catch (error) {
throw new DatabaseQueryException(INTERNAL_SERVER_ERROR, error.message);
}
}
and I'm calling this method in another class.
const getMd = async (load) => {
...
const jobCodeData = await queryRepository.queryByJobCode(jobCode);
const filteredJobCodeData = filterDataUtil.getFilteredJobCodeData(jobCodeData);
}
If I run sonar scanner it is giving me an error saying that
"Refactor this redundant 'await' on a non-promise."
Could you help me please? FYI this works fine in local environment
I am generating data for querying with gatsby's sourceNodes api.
The problem is that inside the getHooksInfo call something weird happens.
I do the first await fetch(rawUrl)(i am using node-fetch, but it doesn't matter that much) request, everything's fine. But when i do the second request const res = await fetch(url) inside for (const guess of guesses) it... does nothing. I see the first console.log('before fetch');, but not the console.log('after fetch');. No error either. It just goes straight to the return statement with result being always []. I tried debugging, but debugger jumped to the return statement also on this line. Even stepping into the actual fetch call didn't help that much. So if you smell anything (besides the code, obviously;D ) here that leads to that behavior, i'd really appreciate your help.
exports.sourceNodes = async ({ actions }) => {
const { createNode } = actions;
...
await Promise.allSettled(someArray
.map(async ({ package: { links, author, description }, score, searchScore }, i) => {
const { npm, homepage, repository } = links;
const { final, detail: { popularity } } = score;
const { ok, result } = await getHooksInfo(repository);
...
createNode(...);
}));
async function getHooksInfo(repository) {
...
const res = await fetch(rawUrl);
if (!res.ok) {
return {
ok: false,
result: null
};
}
const readme = await res.text();
const hooks = [...];
const result = [];
await Promise.allSettled(
hooks.map(async (hook) => {
for (const guess of guesses) {
...
console.log('before fetch');
const res = await fetch(someUrl);
console.log('after fetch');
...
}
})
);
return {
ok: true,
result
};
}
I'm guessing that Promise.allSettled is swallowing some syntax error in your fetch(url) and that that is why you aren't getting errors.
I'm using node and express to create server for my app. This is how my code looks like:
async function _prepareDetails(activityId, dealId) {
var offerInfo;
var details = [];
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected correctly to server");
const db = client.db(dbName);
const offers_collection = db.collection('collection_name');
await offers_collection.aggregate([
{ "$match": { 'id': Id} },
]).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
details = docs;
});
})
return details;
}
app.post('/getDetails',(request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
_prepareDetails(activityId,Id).then(xx => console.log(xx));
response.send('xx');
})
While calling getDetails API I am getting
await is only valid in async function error (At line await offers_collection.aggregate)
I am also getting red underline while declaring async function. Node version I'm using is 11.x. I'm also using firebase API. What am I doing wrong here?
You are missing the async declaration on one of your functions. Here is the working code:
async function _prepareDetails(activityId, dealId) {
var offerInfo;
var details = [];
client.connect(async function(err) {
assert.equal(null, err);
console.log("Connected correctly to server");
const db = client.db(dbName);
const offers_collection = db.collection('collection_name');
await offers_collection.aggregate([
{ "$match": { 'id': Id} },
]).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
details = docs;
});
})
return details;
}
app.post('/getDetails', async (request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
let xx = await _prepareDetails(activityId,Id);
response.send('xx');
})
Await can only be used in an async function, because await is by definition asynchronous, and therefore must either use the callback or promise paradigm. By declaring a function as async, you are telling JavaScript to wrap your response in a promise. Your issue was on the following line:
client.connect(function(err) {
This is where I added the async as mentioned before.
client.connect(async function(err) {
You will notice I made your route use async also, because you would've had an issue before. Notice the two lines in your original code:
_prepareDetails(activityId,Id).then(xx => console.log(xx));
response.send('xx');
Your response would send before you even made your database call because you are not wrapping the response.send within the .then. You could move the response.send into the .then, but if you are going to use async/await, I would use it all the way. So your new route would look like:
app.post('/getDetails', async (request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
let xx = await _prepareDetails(activityId,Id);
response.send('xx');
})