Promise All - Unhandled promise rejection - javascript

Doing some TTD and trying to throw a custom exception I made called FailedToConnectError, but I keep getting my NoAccountFoundError.
Here is my test:
Server.SERVER_URL = 'http://www.test.com.fail';
server.getAccounts(['999999999']).catch(e=>{
expect(e).toBeInstanceOf(FailedToConnectError);
});
The main thing with the next function is we are grouping the account ids into groups of 100's then builds an array of promises to run. (API will only let you look up to 100 accounts at a time):
public getAccounts(accountIDs: string[]): Promise<Account[]>{
return new Promise<Account[]>((resolve, reject) => {
let groupedAccountIds:string[] = this.groupAccountIdsByMaxRquestLimit(accountIDs);
let promises: Promise<Account[]>[] = this.buildPromisesForGroupingAccounts(groupedAccountIds:string);
Promise.all(promises).then(accountProfilePromises => {
let accounts:Account[] = [];
for(let accountProfiles of accountProfilePromises){
for(let accounts of accountProfiles){
accounts.push(accounts);
}
}
if(accounts.length < 1){
reject(new NoAccountFoundError());
}
resolve(accounts);
}).catch(err => {
reject(err);
});
});
}
Here is the buildPromisesForGroupingAccounts when also calls a function to send the http request.
private buildPromisesForGroupingAccounts(groupedIds:string[]){
let promises: Promise<Account[]>[] = [];
for(let accountIdsBy100s of groupedIds){
let get100Accounts = new Promise<Account[]>((resolve, reject) => {
var path = 'accounts/?'+'accounts='+accountIdsBy100s;
this.websiteRequest(path, reject, (r:any,body:any)=>{
let accountsJSON = JSON.parse(body).response.players;
let accounts:Account[] = [];
for(let account of accountsJSON){
accounts.push(account);
}
resolve(accounts);
});
});
promises.push(get100Accounts);
}
return promises;
}
Here is the website request function:
public websiteRequest(path:string, reject: Function, cb: Function){
request.get({
url:Server.SERVER_URL+path
},
async (err,r,body) => {
if(err){
reject(new FailedToConnectError());
}else{
cb(r,body);
}
});
}
Finally this is the error I get when I run my code:
(node:3835) UnhandledPromiseRejectionWarning: Error: expect(value).toBeInstanceOf(constructor)
Expected constructor: FailedToConnectError
Received constructor: NoAccountFoundError
Received value: [Error: No account found]
(node:3835) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3835) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Related

Typescript: issue with async await promise.all looping through all results

Having an issue with this result set due to it being type unknown. I've tried several different things but keep getting the same error and not sure what to do. Thanks for any help!
Here is the error message -
TypeError: Cannot read property 'props' of undefined
at C:\TS\mytask\src\helloworld.js:153:47
at step (C:\TS\mytask\src\helloworld.js:33:23)
at Object.next (C:\TS\mytask\src\helloworld.js:14:53)
at C:\TS\mytask\src\helloworld.js:8:71
at new Promise (<anonymous>)
at __awaiter (C:\TS\mytask\src\helloworld.js:4:12)
at C:\TS\mytask\src\helloworld.js:144:60
at new Promise (<anonymous>)
at searchUsers (C:\TS\mytask\src\helloworld.js:144:12)
at Object.<anonymous> (C:\TS\mytask\src\helloworld.js:173:13)
Promise { <rejected> [] }
(node:37216) UnhandledPromiseRejectionWarning: [object Array]
(Use `node --trace-warnings ...` to show where the warning was created)
(node:37216) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:37216) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Code -
function searchUsers(filterText: string): IPersonaProps[] | Promise<IPersonaProps[]> {
return new Promise(async (resolve: any, reject: any) => {
let People: IPersonaProps[] = [];
try {
const tempPeople = await this.props.context.webAPI.retrieveMultipleRecords("systemuser?$select=fullname,internalemailaddress,systemuserid");
await Promise.all(tempPeople.entities.map((entity: any ) =>{
People.push({ "text": entity.fullname, "secondaryText": entity.internalemailaddress, "id" : entity.systemuserid }); //change fieldname if values are different
}));
resolve(People);
}
catch (err) {
console.log(err);
reject(People);
}
});
}
Currently this works fine for 1 result, but when I try to get back a collection of results and loop through them to push to the People array, I always keep getting the same error.
Thanks again!
It looks like this is a member function of a class you have declared but have not initialized hence this being undefined. To confirm please add the code of how you are using your class...
private _searchUsers(filterText: string): IPersonaProps[] | Promise<IPersonaProps[]> {
return new Promise(async (resolve: any, reject: any) => {
let People: IPersonaProps[] = [];
// This is a reference to a class
const tempPeople = await this.props.context.webAPI.retrieveMultipleRecords("systemuser?$select=fullname,internalemailaddress,systemuserid");
// Need to make the callback function async so that it becomes an array of promises
await Promise.all(tempPeople.entities.map(async (entity: any ) => {
People.push({ "text": entity.fullname, "secondaryText": entity.internalemailaddress, "id" : entity.systemuserid }); //change fieldname if values are different
}));
resolve(People);
}
catch (err) {
console.log(err);
reject(People);
}
});
}
I found the issue. Here's how I was able to get it working. Thanks for the help!
private _searchUsers(filterText: string): IPersonaProps[] | Promise<IPersonaProps[]> {
return new Promise(async (resolve: any, reject: any) => {
let People: IPersonaProps[] = [];
const config = new WebApiConfig("9.1");
const options: string = "?$select=fullname,internalemailaddress,systemuserid";
retrieveMultiple(config, "systemusers", options)
.then(
(results) => {
const People: IPersonaProps[] = [];
for (const record of results.value) {
People.push({ "text": record.fullname, "secondaryText": record.internalemailaddress, "id" : record.systemuserid });
resolve(People);
}
},
(error) => {
reject(People);
console.log(error);
}
);
});
};

UnhandledPromiseRejectionWarning when using .reduce

const sendData = (response, language, locale) => {
try {
console.log(response.reduce((prev, curr) => prev + curr.confirmed, 0));
} catch (error) {
console.error('error');
}
};
and my fetch function:
const fetchGeneralData = async (param) => {
try {
let res = await axios.get(
`https://localhost/api/${param}`,
);
msg.reply(sendData(res.data.results), language, momentLocale);
} catch (error) {
msg.reply(language.errorMessage);
console.error(error, 'Error on fetchGeneralData');
}
};
The console.log shows me the correct value but for some reason, I still getting the errors.
I have tried adding async/await inside sendData but it did not work. My fetchGeneralData func works fine when i'm trying to return the date without modify it.
Here is the full message:
(node:5500) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: t.match is not a function
(node:5500) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:5500) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

How do I handle the UnhandledPromiseRejectionWarning in Node.JS

I have a few methods that use the request module to get images from URLs and returns it as a Promise, it works but when the image isn't found it rejects the promise with the status code 404. I looked into that warning and it is said that to handle the rejection you have to setup a catch callback after then() but I don't use then(), I use async/await.
This is the code to get the picture:
/**
* Returns picture from S3
* #param {String} filename Name of the file with extension
* #returns {String} Base64 string of the file
*/
getPictureFromS3: function (filename) {
return new Promise((resolve, reject) => {
let url = this.getURLFromS3(filename);
request(url, (err, res, body) => {
if (err) reject(err);
if (res.statusCode !== 200) {
reject(`Invalid status code <${res.statusCode}>`);
}
resolve(new Buffer.from(body).toString('base64'));
});
});
}
And this is how I call the method:
try{
socket.on('server get pictures', () => db.getPictures(data=>{
if(data!==null){
data.forEach(async e=>{
let picture = await utils.getPictureFromS3(e.getFilename());
});
}
}));
}catch(err){
console.log(err);
}
Full warning:
(node:256) UnhandledPromiseRejectionWarning: Invalid status code <404>
(node:256) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which
was not handled with .catch(). (rejection id: 1)
(node:256) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Using Node v10.14.2.
There are two problems here
You care trying to do async operation inside forEach which doesn't work with promises. You need to use for..of loop or Promise.all if you can do things in parallel.
The exception is raise inside the listener so it will not bubble up outside so your catch wouldn't be executed. You need to move your try catch inside. Something like this
socket.on("server get pictures", () =>
db.getPictures(data => {
if (data !== null) {
for(const e of data) {
try {
let picture = await utils.getPictureFromS3(e.getFilename());
} catch (err) {
console.log(err);
}
}
}
})
);

I cant handle promise rejections

I have a service that analyses websites, compresses their sources like CSS Documents, Images etc. I have 2 functions, one is Socket.IO socket.on() method with async callback function. Another is main function for service.
socket.on('run', async options => {
debug(`${options.target} Adresine Bir Kullanıcı İstek Yaptı!`);
let user = null;
console.log(options);
if(options.token) {
user = await User.findById(jwt.verify(options.token, config.get('jwtPrivateKey'))._id);
options.userId = user._id.toString();
} else if(options.visitor) {
user = await Visitor.findById(options.visitor._id);
if(user.report) {
return socket.emit('error', new Error('You have exceeded your report limit'));
} else {
options.userId = user._id.toString();
}
}
if(options.userId) {
let userType = await UserType.find({ name: user.type });
if(userType.length > 0 && ((user.type == 'Visitor' && user.report == undefined) || (user.reports.length < userType[0].rights.reportsLimit.limit || userType[0].rights.reportsLimit.unlimited))) {
options.rights = userType[0].rights;
let { error, data } = await wrapper(runService(options.target, options, socket));
if(error) {
console.log('Here', error);
return socket.emit('error', error);
}
.
.
.
}
.
.
.
}
});
In the above function,
let { error, data } = await wrapper(runService(options.target, options, socket));
if(error) {
console.log('Here', error);
return socket.emit('error', error);
}
This part is important, because I call my main async service function runService with my async function wrapper function that is named wrapper. The wrapper function is this;
const wrapper = promise => (
promise
.then(data => ({ data, error: null }))
.catch(error => ({ error, data: null }))
);
In my main async service function, I only throw an error;
async function runService(target, options, socket) {
throw new Error('any error');
}
But the expected output is much different from actual output. Here is the output of this code;
Here Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16600) UnhandledPromiseRejectionWarning: Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16600) UnhandledPromiseRejectionWarning: Unhandled promise rejection.
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:16600) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate
the Node.js process with a non-zero exit code.
My expectation about the output is, like this;
Here Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
Because I already handled the promise rejection with my wrapper function and catched the rejection, Why is 2 more UnhandledPromiseRejectionWarning errors on rejection?
Also, the line,
return socket.emit('error', error);
is not calling for no reason. It should have been called when the if statement truthy. Why is not this socket.emit function called?
As best practice use try {} catch(){} with async/await.
For ex.
userUtils.signUp = async (userName) => {
try {
const callFunction = await userUtils.checkExistancy(userName);
if (!callFunction.isExist) {
...
} else {
...
}
} catch (err) {
console.log(err);
throw err;
}
};
in your case it will be like
socket.on('run', async options => {
try {
user = await User.findById(jwt.verify(options.token, config.get('jwtPrivateKey'))._id);
options.userId = user._id.toString();
return true;
} catch (err) {
throw err;
}});

When start code in Promise in Node.js ES6?

I make a method that create a promise for each element in array.
queries.push(function (collection) {
new Promise((resolve, reject) => {
collection.find({}).limit(3).toArray(function (err, docs) {
if (err) reject(err);
resolve(docs);
});
});
});
const getAnalyticsPromises = (collection) => {
let promises = [];
queries.each((item) => {
promises.push(item(collection));
});
console.log(queries);
return promises;
}
This code return this errors:
(node:10464) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: queries.each is not a function
(node:10464) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
The question is: When the promise is called? When i create it:
promises.push(item(collection));
or when i call it with then() function?
Well the error you have is about queries has not method each - you should use forEach instead.
Bescides you should return promise from your function:
queries.push(function (collection) {
return new Promise((resolve, reject) => {
collection.find({}).limit(3).toArray(function (err, docs) {
if (err) reject(err);
resolve(docs);
});
});
});
So when you call item(collection) where item is one of your anonymous functions, the promise would be created.
And now you can handle with it whatever you need, for example:
let p = item(collection);
p.then(...).catch(...)

Categories

Resources