Implementation of async also not working angular2+ - node.js

I have made a function in my angular2+ component and the output comes first and the function runs later and hence the appropriate output which i want comes later. The function passes a variable parameter along with the http request to the back-end NodeJS. And returns the result. I want to find its length which i am able to retrieve. However, i want to call this parameter more than once by passing multiple parameters. So i defined it as Asynchronous function. The code is as -
app.component.ts
// Function 1
getNodesCount() {
console.log("INSIDE getNodesCount()")
if (this.selectedAPIName.length == 1) {
this.nodesObjQ1 = {
'relationObj': this.menuItem,
'nodeValue1': this.selectedAPIName[0]
}
this.callFunctionCount(this.nodesObjQ1).then((rs: any[])
=> {
this.nodesObjL1 = rs;
});
console.log("this.nodesObjL1 =", this.nodesObjL1)
}
}
//Function 2
async callFunctionCount(trueNodesObject) {
console.log("nodesObj =", trueNodesObject);
await new Promise(next => {
this.http.get("http://localhost:3003/seekExtraction/nodesObj/" +
JSON.stringify(trueNodesObject))
.map(Response => Response)
.catch((err) => {
console.log("err =", err)
return Observable.throw(err);
})
.subscribe((res: Response) => {
console.log("XXXXXXXXXXXX Response on /seekExtraction",
res);
this.nodesInfo = res;
this.nodesLength = this.nodesInfo.records.length
next()
})
});
console.log("return this.nodesLength =", this.nodesLength)
return this.nodesLength;
}
Major Outputs -
this.nodesObjL1 = undefined
return this.nodesLength = 2
Please help to retrieve this value -
this.nodesObjL1
after this value
this.nodesInfo.records.length= 2

actual minimal example would have helped ensure clean code... but give this a go...
getData = function (trueNodesObject) {
return new promise((resolve, reject) => {
this.http.get("http://localhost:3003/seekExtraction/nodesObj/" +
JSON.stringify(trueNodesObject))
.map(Response => Response)
.catch((err) => {
console.log("err =", err)
return Observable.throw(err);
reject(err);
})
.subscribe((res: Response) => {
console.log("XXXXXXXXXXXX Response on /seekExtraction",
res);
this.nodesInfo = res;
this.nodesLength = this.nodesInfo.records.length
resolve(this.nodesLength);
next()
});
})
}
async function callFunctionCount(trueNodesObject) {
console.log("nodesObj =", trueNodesObject);
const someVal = await getData(trueNodesObject);
console.log("return this.nodesLength =", someVal)
}

Related

Make possible to get rejected value

I hope someone can help me out with my issue to get back the reject value out of this functions:
(async () => {
await queue.add(() => startCompare(orgpath, dpath, xray));
console.log('done compare ' + entry);
})();
This call the function:
async function startCompare(orgFile, compFile, xFile)
{
let gstderr;
return new Promise((resolve, reject) => {
spawn('compare', [orgFile, compFile, '-metric', 'AE', 'null:'])
.progress(function (childProcess) {
childProcess.stdout.on('data', function (data) {
console.log('[spawn] stdout: ', data.toString());
});
childProcess.stderr.on('data', function (data) {
gstderr = data.toString();
console.log('[spawn] stderr: ', data.toString());
});
}).then(res => {
resolve(true);
}).catch(error => {
resolve(gstderr);
});
});
}
My goal is how to get back gstderr value when rejected. Maybe the arrow function is the wrong way? I want to print out the value at: console.log('done compare ' + entry + xxxxx); where xxxxx is the rejected value.
You can catch the rejected value of a promise with async/await by using try/catch like so:
(async () => {
try {
// if it gets resolved lands here
const result = await startCompare(...args)
console.log(result) // should be true
} catch(error) {
// if it gets rejected it lands here
console.log(error) // should be the gstderr
}
})()
Hope it helps!
export const canLogin = createAsyncThunk("AUTH/login",
async (loginData ,{ rejectWithValue })=> {
try{
const response=await axios.post(AuthConfig.API_URL + AuthConfig.LOGIN_URI, loginData)
return response
}
catch(error){
if (!error.response || !error.message)
throw error
return rejectWithValue(getErrorMessage(error))
}
}
);
export function getErrorMessage(error) {
return (
error?.response?.data?.message ||
error?.response?.data.error ||
error?.response?.data ||
error?.message ||
error.toString()
);
}

AWS Lambda NodeJS, can't make external connection

So, I'm trying to do a basic thing: Connect to an external REST-API from my AWS Lambda script.
This API hosts a list of holidays.
But, whenever I try to execute the code it just times out (max lambda execution time reached).
So I created this wrapper function, that is capable of handling 4 different ways of doing GET requests, but all of them perform the same.
const request = require('request')
const https = require('https')
const axios = require('axios')
const superagent = require('superagent')
let test = (type = "") => {
return new Promise((resolve, reject) => {
debug("Fetching with: " + type)
const d = new Date()
if(type == "superagent"){
superagent.get('https://holidayapi.pl/v1/holidays?country=DK&year=' + d.getFullYear())
.query({ country: 'DK', year: '2019' })
.end((err, res) => {
if (err) {
console.log(err)
reject(err)
} else {
console.log(res)
resolve(res)
}
})
} else if(type == "axios"){
axios.get('https://holidayapi.pl/v1/holidays?country=DK&year=' + d.getFullYear())
.then(response => {
debug(response)
resolve(response)
})
.catch(error => {
console.log(error)
reject(error)
})
} else if(type == "https"){
const req = https.get("https://holidayapi.pl/v1/holidays?country=DK&year=" + d.getFullYear(), (resp) => {
let data = ''
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk
})
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation)
resolve([])
})
})
.on('error', (e) => {
debug(e)
reject(e.message)
})
req.end()
} else if(type == "request"){
request('https://holidayapi.pl/v1/holidays?country=DK&year=' + d.getFullYear(), { json: true }, (err, res, body) => {
debug(err)
debug(res)
debug(body)
if (err) reject(err)
else resolve(body.holidays)
})
} else {
reject("Mangler type")
}
})
}
exports.connect_test = (event, context, callback) => {
test(event.pathParameters.type)
.then((rsp) => {
callback(null, JSON.stringify(rsp, null, 2))
})
.catch((err) => {
callback(null, JSON.stringify(err, null, 2))
})
}
The debug function is a map to console.log, that checks if the NODE_ENV is "dev".
I presume the default VPC has got internet connectivity, So if it's in the default it should just work (just increase the default timeout on the lambda to something reasonable).
If its inside a VPC then you need to have NAT Gateway/NAT instance configured for that VPC to have internet connection or pair with another VPC that has an internet access(Inside the VPC lambda need to have appropriate role and subnet).
This might help you aws docs

use answer .then () outside and use in another part of the code in node js

How can I use the answer of a promise outside of. Then what should I do?
arreglo.forEach((item) => {
if (item.tipoCampo == 3) {
self.campoSelects(item.tablaCampo)
.then(resp => {
console.log(resp)
})
.catch(e => console.log(e))
}
});
console.log (resp) inside the .then () knows it and prints correctly, but when I want to know resp out of the forEach to use below, it says undefined
Thanks.
arreglo.forEach((item) => {
if (item.tipoCampo == 3) {
self.campoSelects(item.tablaCampo)
.then(resp => {
logMyData(resp);
})
.catch(e => console.log(e))
}
});
logMyData=(x)=>{
console.log(x);
}
This is just as simple as adding a helper function which executes inside your .then
Guessing that you want to be able to access the value within the forloop. Since self.campoSelects is a promise we can use async await.
// Call campo selects
function getCampoSelects(_self, tablaCampo) {
return new Promise(async (resolve, reject) => {
let campoData;
try {
campoData = await _self.campoSelects(tablaCampo);
} catch (err) {
reject(err);
}
resolve(campoData);
});
}
function happyLittleFunc() {
const arreglo = [];
arreglo.forEach(async (item) => {
if (item.tipoCampo === 3) {
let campoSelect;
// Unsure if you are setting self somewhere but it can be passed in here.
try {
campoSelect = await getCampoSelects(self, item.tipoCampo);
} catch (err) {
console.log(err);
return;
}
console.log(campoSelect);
}
});
}
happyLittleFunc();

.then of Promise.all not executing

I'm using firestore to retrieve data which has the following DS.
I have a Company collection which contains a subcollection Branches
So I'm trying to retrieve to list all the Companies with its Branches
Code:
exports.findAll = function (req, res) {
getcompanies().
then((companies) => {
console.log("Main "+ companies) // info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
return res.json(companies);
})
.catch((err) => {
console.log('Error getting documents', err);
});
}
function getCompanies(){
var companiesRef = db.collection('companies');
return companiesRef.get()
.then((snapshot) => {
let companies = [];
return Promise.all(
snapshot.forEach(doc => {
let company = {};
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) => {
company.branches = branches;
companies.push(company);
if(snapshot.size === companies.length){
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
}
return Promise.resolve(companies);
})
.catch(err => {
console.log("Error getting sub-collection documents", err);
return Promise.reject(err);
})
})
)
.then(companies => {
console.log("Outside " + companies) // This is never executed
return companies;
})
.catch(err => {
return err;
});
})
.catch(err => {
return err;
});
}
function getBranchesForCompanyById(id){
var branchesRef = db.collection('companies').doc(id).collection('branches');
let branches = [];
return branchesRef.get()
.then(snapshot => {
snapshot.forEach(brnch => {
let branch = {};
branch.id = brnch.id;
branch.branch = brnch.data();
branches.push(branch);
})
return branches;
})
.catch(err => {
return err;
})
}
I've all the data needed at this point.
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
But the then of Promise.all is never executed. So getting this error -
info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
console.log("Main "+ companies) // info: Main TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
I feel I have followed all the rules specified here: https://stackoverflow.com/a/31414472/2114024 with respect to nested promises, not sure where I'm missing the point.
Thanks in advance!
I see at least 2 problems:
forEach likely doesn't return anything, and you send the result of forEach into Promise.all().
If Promise.all() throws an exception, some of your catch handlers just grab the error and return it. Returning it turns it into a non-exception.
You also really don't have to add a catch to every Promise chain, as long as you feed the result of a Promise chain back into another promise chain, you probably only need 1 catch block.
Also one of your then() functions should not be nested as deeply. Just move it a level up, that's the point of promises.
In your code, you can use map instead of forEach. Promise.all accept an array of promises but forEach does not return an array
return Promise.all(
snapshot.map(doc => {
let company = {};
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) => {
company.branches = branches;
companies.push(company);
if (snapshot.size === companies.length) {
console.log("companies - Inside" + JSON.stringify(companies)); //This prints all companies with its branches
}
return Promise.resolve(companies);
})
.catch(err => {
console.log("Error getting sub-collection documents", err);
return Promise.reject(err);
})
})
)
Based on inputs from Evert and Rahul, thanks to both of you, I have resolved the problem here.
I handled all the error in the catch block
Promise.all was not returning anything so I converted the forEach to map.
So this is my updated code, which solves the problem:
exports.findAll = function (req, res) {
getcompanies().
then((companies) => {
console.log("Main " + companies) // Prints all companies with its branches
return res.json(companies);
})
.catch((err) => {
console.log('Error getting documents', err);
return res.status(500).json({ message: "Error getting the all companies" + err });
});
}
function getCompanies() {
var companiesRef = db.collection('companies');
return companiesRef.get()
.then((snapshot) => {
let companies = [];
return Promise.all(
snapshot.docs.map(doc => {
let company = {};
company.id = doc.id;
company.company = doc.data();
var branchesPromise = getBranchesForCompanyById(company.id);
return branchesPromise.then((branches) => {
company.branches = branches;
companies.push(company);
if (snapshot.size === companies.length) {
console.log("companies - Inside" + JSON.stringify(companies));
return companies;
}
})
.catch(err => {
console.log("Error getting sub-collection documents", err);
throw new Error(err);
})
})
)
.then(companies => {
console.log("Outside " + companies); // Executed now
return companies[companies.length - 1];
})
.catch(err => {
throw new Error(err);
});
})
.catch(err => {
throw new Error(err);
});
}
function getBranchesForCompanyById(id) {
var branchesRef = db.collection('companies').doc(id).collection('branches');
let branches = [];
return branchesRef.get()
.then(snapshot => {
snapshot.forEach(brnch => {
let branch = {};
branch.id = brnch.id;
branch.branch = brnch.data();
branches.push(branch);
})
return branches;
})
.catch(err => {
throw new Error(err);
})
}

My second promise gets called before getting the data from the first one resulting in an undefined. Not sure what I am doing

After the underPrice function call, it goes straight to the next promise call and returns undefined, then goes to under price. I am not sure what I am doing wrong any help would be really appreciated. The data is there as undrPrice gets the keys and if I put a console.log - it prints it out. The issues is the second then statement goes off without the first one being done
/// grab all online
var getActiveData = (payload) => {
pub.smembers('partner:services:' + payload.services)
.then((data) => {
Promise.all(data.map(underPrice.bind(this, payload)))
})
.then((data) => {
Promise.all(console.log(data));
});};
Here is the underPrice code
var underPrice = (payload, key) => {
return new Promise((resolve, reject) => {
pub.hmget(key + ":services:" + payload.services, "amount", (err, data) => {
if (err) reject(err); //will display '1, 3, 5, 7'
else {
data <= payload.price ? resolve(key) : reject(key);
}
});
});
};
You are forgetting to return the promises from your functions, especially from the then callbacks, so the caller will have nothing to wait for.
function getActiveData(payload) {
return pub.smembers('partner:services:' + payload.services)
// ^^^^^^
.then(data => {
return Promise.all(data.map(underPrice.bind(this, payload)))
// ^^^^^^
})
.then(data => {
console.log(data);
return data;
// ^^^^^^
});
}

Resources