using async await in node js? - node.js

I am trying to implement async/await module. In function2 if user is not present i want to stop the execution there . i dont want to execute function 3, if user present , i want to execute function3
const function1() {
//code
return a
}
const function2= (a,email) => model.user.findOne({ email:email}).then((user) => {
if (!user) {
****// want to stop execution here****
} else {
//update details of user
}
return dealer;
});
const function 3 = function(dealer) {
//mail sending
};
exports.mailer = async(email,callback) => {
try {
var a =await function1();
var dealer =await function2(a,email); //stop execution here
var res = await function 3(dealer);
await callback(res);
}catch (err){
callback(err);
}
}

Returning a new Promise in function2 which resolves if a user is found, and rejects if not should achieve what you want I believe.
Something like this:
const function1 = () => {
return a
}
const function2 = (a, email) => {
return new Promise((resolve, reject) => {
model.user.findOne({
email: email
}).then((user) => {
if (!user) {
// want to stop execution here****
reject(new Error('Error Message'))
} else {
// update details of user
resolve(dealer)
}
})
})
}
const function3 = (dealer) => {
//mail sending
}
exports.mailer = async (email, callback) => {
try {
var a = await function1()
var dealer = await function2(a, email) // stop execution here
var res = await function3(dealer)
await callback(res)
} catch (err) {
callback(err)
}
}

Related

async/await troubles in a recursive Redis function

Ima rookie using async/await but must now to use Redis-om. NN_walkd walks through a Redis database looking for loop-chains and does this by recursion. So the 2 questions I have is:
Am I calling the inner recursive NN_walkd calls correctly via async/await?
At runtime, the compSearchM proc is called first and seems to work (it gets 5 entries so it has to call NN_walkd 5 times). A NN_walkd is then recursively called, and then when it loops the 1st time it then calls compSearchK where the problems are. It seems to sit on the first Redis call in compSearchK (.search). Yet the code for compSearchK and compSearchM look basically identical.
main call
NN_walk = async function(req, db, cnode, pnode, chain, cb) {
var vegas, sneaker;
req.session.walk = [];
await NN_walkd(req, cnode, pnode, [], 1);
req.session.walk = null;
console.log('~~~~~~~~~~~~ Out of Walk ~~~~~~~~~~~~~~~');
cb();
};
redis.mjs
export class RedisDB {
constructor() {
...
this._companyRepo = ...
}
compSearchK(ckey) { // doesn't matter if I have a async or not here
return new Promise(async (resolve) => {
const sckey = await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
if (sckey.length) {
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
resolve(ttrr.toJSON());
} else
resolve(null);
});
}
compSearchM(mkey) {
var tArr=[];
return new Promise(async (resolve) => {
const smkey = await this._companyRepo.search()
.where('MASTERKEY').equals(mkey)
.and('TBLNUM').equals(10)
.return.all();
if (smkey.length) {
for (var spot in smkey) {
const ttrr = await this._companyRepo.fetch(smkey[spot].entityId);
tArr.push(ttrr.toJSON());
}
resolve(tArr);
} else {
resolve(null);
}
});
}
walk.js
NN_walkd = async function(req, cnode, pnode, chain, lvl) {
...
if (cnode[1]) {
const sObj = await req.app.get('redis').compSearchK(cnode[1]);
if (sObj) {
int1 = (sObj.TBLNUM==1) ? null : sObj.CLIENTKEY;
(async () => await NN_walkd(req, [sObj.COMPANYKEY,int1], cnode, Array.from(chain), tlvl))()
}
} else {
const sArr = await req.app.get('redis').compSearchM(cnode[0]);
if (sArr.length) {
for (sneaker in sArr) {
(async () => await NN_walkd(req, [sArr[sneaker].COMPANYKEY,sArr[sneaker].CLIENTKEY], cnode, Array.from(chain), tlvl))()
}
} else {
console.log('no more links on this chain: ',cnode);
}
}
}
"doesn't matter if i have async or not here"
compSearchK(ckey) { // doesn't matter if I have a async or not here
return new Promise(async (resolve) => {
const sckey = await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
if (sckey.length) {
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
resolve(ttrr.toJSON());
} else
resolve(null);
});
}
Of course it doesn't matter, because you're not using await inside of compSearchK!
You are using the explicit promise contructor anti-pattern. You should avoid it as it demonstrates lack of understanding. Here is compSearchK rewritten without the anti-pattern -
async compSearchK(ckey) {
// await key
const sckey =
await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
// return null if key is not found
if (sckey.length == 0) return null;
// otherwise get ttrr
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
// return ttrr as json
return ttrr.toJSON();
}

Socket Hangup error in Nodejs for multiple API calls

I am trying to fetch a list of all companies listed in stock market from an external API, and after getting the list, I am trying to fetch all details regarding individual companies including graph data. It was all working fine. However, today I am getting socket hangup error. I have tried going through other posts here in stackoverflow. However, none of them works.
const request = require('request');
const fetchAPI = apiPath => {
return new Promise(function (resolve, reject) {
request(apiPath, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
// get list of all companies listed in
const fetchCompanyDetails = () => {
return new Promise(function (resolve, reject) {
let details = [];
fetchAPI('https://api//')
.then(res => {
res = JSON.parse(res)
details.push(res);
resolve(details);
})
.catch(err => {
console.log("error at fetchcompany details" + err);
})
});
}
const getDateAndPriceForGraphData = (graphData) => {
let res = []
graphData.forEach(data => {
let d = {}
d["x"] = new Date(data.businessDate).getTime() / 1000
d["y"] = data.lastTradedPrice
res.push(d)
})
return res
}
// get graph data for individual assets
const getGraphDataForAssets = (assetID) => {
return new Promise((resolve, reject) => {
let details = {};
fetchAPI(`https://api/${assetID}`)
.then(async (res) => {
res = JSON.parse(res)
let data = await getDateAndPriceForGraphData(res)
details = data
resolve(details);
})
.catch(err => {
console.log("error at getGraphDataForAssets" + err);
})
});
}
// fetch data about individual assets
const fetchAssetDetailsOfIndividualCompanies = (assetID) => {
return new Promise((resolve, reject) => {
let details = {"assetData" : {}, "graphData": {}};
fetchAPI(`https://api/${assetID}`)
.then(async (res1) => {
res1 = JSON.parse(res1)
details["assetData"] = res1
// get graph data
var graphData = await getGraphDataForAssets(assetID)
details["graphData"] = graphData
resolve(details);
})
.catch(err => {
console.log("error at fetchAssetDetailsOfIndividualCompanies" + err);
reject(err)
})
});
}
// returns list of details of all tradeable assets (Active and Suspended but not delisted)
const fetchDetailsForEachCompany = async (companyList) => {
let result = []
await Promise.all(companyList.map(async (company) => {
try {
// return data for active and suspended assets
if(company.status != "D") {
let companyData = await fetchAssetDetailsOfIndividualCompanies(company.id)
result.push(companyData)
}
} catch (error) {
console.log('error at fetchDetailsForEachCompany'+ error);
}
}))
return result
}
exports.fetchAssetDetails = async () => {
let companyDetails = await fetchCompanyDetails()
let det = await fetchDetailsForEachCompany(companyDetails[0])
return det
}
To expand on what I meant with not needing those new Promise()s, this would be an idiomatic async function refactoring for the above code.
I eliminated getGraphDataForAssets, since it was eventually not used; fetchAssetDetailsOfIndividualCompanies fetched the same data (based on URL, anyway), and then had getGraphDataForAssets fetch it again.
const request = require("request");
function fetchAPI(apiPath) {
return new Promise(function (resolve, reject) {
request(apiPath, function (error, response, body) {
if (!error && response.statusCode === 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
async function fetchJSON(url) {
return JSON.parse(await fetchAPI(url));
}
async function fetchCompanyDetails() {
return [await fetchAPI("https://api//")];
}
function getDateAndPriceForGraphData(graphData) {
return graphData.map((data) => ({
x: new Date(data.businessDate).getTime() / 1000,
y: data.lastTradedPrice,
}));
}
// fetch data about individual assets
async function fetchAssetDetailsOfIndividualCompanies(assetID) {
const assetData = await fetchJSON(`https://api/${assetID}`);
const graphData = getDateAndPriceForGraphData(assetData);
return { assetID, assetData, graphData };
}
// returns list of details of all tradeable assets (Active and Suspended but not delisted)
async function fetchDetailsForEachCompany(companyList) {
const promises = companyList.map(async (company) => {
if (company.status === "D") return null;
return fetchAssetDetailsOfIndividualCompanies(company.id);
});
const results = await Promise.all(promises);
return results.filter(Boolean); // drop nulls
}
async function fetchAssetDetails() {
const companyDetails = await fetchCompanyDetails();
return await fetchDetailsForEachCompany(companyDetails[0]);
}
exports.fetchAssetDetails = fetchAssetDetails;

Question about nodejs using 'async-lock' return value

I used async-lock module for my typescript program of concurrency.
As I use this, I want to return the result in lock.acquire(...) {...}, but it's not working well.
How can I return the value? I'll be grateful for any advice about this. Thanks!
public async getValue(key: string): Promise<any> {
const base = this;
lock.acquire(key, async function (done) {
base.logger.info(`${key} lock enter`);
if (!await base.myRepository.checkDBTable(key)) {
const valueFromNetwork: number = await base.getValueFromNetwork(key);
const initResult: MyEntity = await base.myRepository.initNonce(key, valueFromNetwork);
if (!initResult) {
throw new Error('initValue failed...');
}
base.logger.debug(JSON.stringify(initResult, null, 4));
}
const valueFromDB: number = await base.myRepository.getValueFromDB(key);
if (valueFromDB === -1 || valueFromDB === undefined) {
throw new Error('getValueFromDB failed...');
} else {
const updateResult: MyEntity = await base.myRepository.updateValue(key, valueFromDB);
if (!updateResult) {
throw new Error('updateValue failed...');
}
base.logger.info(`${valueFromDB}`);
base.logger.info(`${key} lock done`);
done();
}
// I'd like to return valueFromDB above.
});
}
You have two options:
You can implement a wrapper around lock.aquire (Recommended as it is a little easier to read and can handle acquisition errors):
public async getValue(key: string): Promise<any> {
const base = this;
const done = await this.aquireLock(key);
base.logger.info(`${key} lock enter`);
if (!await base.myRepository.checkDBTable(key)) {
const valueFromNetwork: number = await base.getValueFromNetwork(key);
const initResult: MyEntity = await base.myRepository.initNonce(key, valueFromNetwork);
if (!initResult) {
throw new Error('initValue failed...');
}
base.logger.debug(JSON.stringify(initResult, null, 4));
}
const valueFromDB: number = await base.myRepository.getValueFromDB(key);
if (valueFromDB === -1 || valueFromDB === undefined) {
throw new Error('getValueFromDB failed...');
} else {
const updateResult: MyEntity = await base.myRepository.updateValue(key, valueFromDB);
if (!updateResult) {
throw new Error('updateValue failed...');
}
base.logger.info(`${valueFromDB}`);
base.logger.info(`${key} lock done`);
done();
}
return valueFromDB;
}
private async aquireLock(key: string): Promise<() => void> {
return new Promise((resolve, reject) => {
lock.acquire(key, done => {
resolve(done);
}, (err)=>{ // in case our aquire fails(times out, etc.)
if(err){
reject(err);
}
})
})
}
Playground
Or, you can use a function constructor (even if it is an anti-pattern):
getValue(key: string): Promise<any> {
return new Promise((resolve, reject) => {
const base = this;
lock.acquire(key, async function (done) {
base.logger.info(`${key} lock enter`);
if (!await base.myRepository.checkDBTable(key)) {
const valueFromNetwork: number = await base.getValueFromNetwork(key);
const initResult: MyEntity = await base.myRepository.initNonce(key, valueFromNetwork);
if (!initResult) {
reject(new Error('initValue failed...'));
}
base.logger.debug(JSON.stringify(initResult, null, 4));
}
const valueFromDB: number = await base.myRepository.getValueFromDB(key);
if (valueFromDB === -1 || valueFromDB === undefined) {
reject(new Error('getValueFromDB failed...'));
} else {
const updateResult: MyEntity = await base.myRepository.updateValue(key, valueFromDB);
if (!updateResult) {
reject(new Error('updateValue failed...'));
}
base.logger.info(`${valueFromDB}`);
base.logger.info(`${key} lock done`);
done();
}
resolve(valueFromDB)
});
})
}
Playground (Many things stubbed out, but it gets the general idea across)

Can't return data from callback function at NodeJS

When i create new variable and assign callback function, But data cannot return from callback function. Undefined is occurring at new variable.
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
console.log(s);
var s is undefined! ....
You are mixing up callback and Promise which are two different way to handle asynchronous calls.
I recommend you to use of Promises because they are simpler and the present and future of javascript.
Using async/await which is the next step after Promises
const user = {
find: () => ['jon', 'kalessi', 'jorah'],
};
async function getUsers() {
return (await user.find({})) || [];
}
async function myJob() {
const users = await getUsers();
console.log(users);
// Put your next code here
}
myJob();
Full promise :
const user = {
find: () => new Promise((resolve) => resolve(['jon', 'kalessi', 'jorah'])),
};
user.find({})
.then((docs = []) => {
console.log(docs);
// Put you next code here, you can use of the variable docs
})
.catch((err) => {
console.log(err);
});
Full callback :
const user = {
find: (_, callback) => callback(false, ['jon', 'kalessi', 'jorah']),
};
user.find({}, (err, docs = []) => {
if (err) {
console.log(err);
} else {
console.log(docs);
// Put you next code here, you can use of the variable docs
}
});
I think user.find returning the promise. you can do like this.
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
Promise.all(s)
.then(result => {
console.log(result);
});
Otherwise you can also use await Like this:
async function abc(){
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = await user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
}
because await worked with async thats why i put it into async function.

why mongoose queries dos not work when put inside promise function

My code is as shown below:
checkAndCreateUser(customer_id, email_id).then(result => {
console.log("result is " + result);
});
var checkAndCreateUser = function (custom_id, email) {
return new Promise(function (resolve, reject) {
if ((!custom_id) && (custom_id.trim() == '')) {
var creatUser = new user();
// creatUser._id = user_id;
creatUser.ph_no = ph_no;
creatUser.email_id = email;
console.log("fn works");
user.findOne({
'email_id': email
}, function (err, user) {
console.log("db test");
if (!user) {
creatUser.save(function (err, userInfo) {
if (err) {
reject("no id found");
} else {
customer_id = userInfo._id;
resolve(customer_id);
}
});
} else {
customer_id = user._id;
resolve(customer_id);
}
});
}
});
}
Now what happens here is I am not able to successfully run db query. I am able to get console.log("fn works") printed , but it does not print console.log("db test"). So what exactly is going wrong?
You forgot save your user, besides Mongoose already returned promise, you don't need use callbacks:
var checkAndCreateUser = function (custom_id, email) {
return User.create({ ph_no :ph_no,
email_id :email})
.then(result=>{
return User.findOne({'email_id': email})
})
.then(user=>{
return user._id;
})
};
As for mistake in your function:
...
let user = new User({email_id: email, ph_no: phone});
user.save();//you forgot about this
...
You can use save() with callback:
user.save((err, result)=>{...});
Or with promise:
user.save().then(result=>{...}).catch(err=>{...});

Resources