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(...)
Related
For example, making two calls with fetch() (second one inside the .then()), do you need two .catch() or only the outside one is enough?
I have tried to replicate but couldn't so far.
b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Solving...');
resolve('solved');
}, 3000);
})
.then(() => {
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Rejecting...');
reject('error');
}, 1000);
})
.then(() => null)
.catch((error) => {
console.log('Catching error inside.');
console.log(error);
});
})
.catch((error) => {
console.log('Catching error outside.');
console.log(error);
});
This works, but if I remove the inner catch() I get Unhandled promise rejection error
Solving...
Rejecting...
(node:73650) UnhandledPromiseRejectionWarning: error
(node:73650) 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:73650) [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.
You need to return the promise in then blocks to be able to catch them in one chain:
b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Solving...');
resolve('solved');
}, 3000);
})
.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Rejecting...');
reject('error');
}, 1000);
});
})
.then(() => null) // You can get rid of this if you don't have anything to do here
.catch((error) => {
console.log('Catching error outside.');
console.log(error);
});
This should also be the preferred way. Having nested chaining as you have in your code sample will make the code very hard to read.
No need to multiple catch(). if any error detected then goes to catch()
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);
}
}
}
})
);
Consider this code:
var p = new Promise(function(resolve, reject){
console.log("run");
setTimeout(reject, 5);
});
p.catch(function() {
console.log("cought!");
});
p.then(function() {
console.log("then!");
});
Output (browser):
run
cought!
Here, in the browser it behaves like expected. Bun ran as a node-script I get:
run
cought!
(node:13927) UnhandledPromiseRejectionWarning: undefined
(node:13927) 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:13927) [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.
So the rejection got catched, but node is still complaining - why that?
I could chain everything together as suggested here and here:
new Promise(function(resolve, reject){
console.log("run");
setTimeout(reject, 5);
}).then(function() {
console.log("then!");
}).catch(function() {
console.log("cought!");
});
Output (browser and node):
run
cought!
In my usecase I can't use this solution, because I have a factory-function which builds the Promise. The catch- and then-functions shall be attached by the factory's caller.In case of then-function it works, but not for catch. How could I avoid this warning?
Promises are multicast, so each time you call .then or .catch you get a new promise object (chain) back. That is, p.then and p.catch both return their own separate promise objects. This means that there is no catch path for p.then.
If chaining the promises together is not possible, then you'll have to handle the error in the new promise chain created by .then. You can swallow this exception if you so choose, but it is a separate exception:
p.then(function() {
console.log("then!");
}).catch(() => {});
I am using Async Await to solve this problem hope it helps, works fine in my computer.
const iReturnPromise = () => {
return new Promise((resolve, reject) => {
console.log("run");
setTimeout(reject, 5);
});
}
async function displayPromiseResults() {
try {
await iReturnPromise();
console.log('!then');
}
catch(ex) {
console.log("cought!");
}
}
displayPromiseResults();
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.
I am trying to get return an mysql data using promises and it works, but when I try to create an error in mysql on purpose but then I am getting this error .
(node:28464) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Users not found
(node:28464) 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.
I checked everywhere and it says to use .catch but its odd that I am using catch but cannot figure out the problem. Normally I would like to know how to solve this instead of just continuing without knowing the right way.
This is the model..
getAllUser =
new Promise((resolve, reject) => {
db.query('SELECT * from users', function (error, results, fields) {
if (error){
return reject('Users not found');
}else{
resolve(results[0]);
}
});
});
module.exports = {
getAllUser
};
And here is how I am calling the model, the model in the top should return an error since the mysql table is called user not users.
router.get('/db',(req,res,next)=>{
getAllUser.then((result)=>{
console.log(result);
}).catch((e) => {
console.log(e);
});
});
You have error in your model file. Function which return promise should be created instead Promise.
Working code:
Model:
getAllUser = () => new Promise((resolve, reject) => {
db.query('SELECT * from users', function (error, results, fields) {
if (error){
return reject('Users not found');
}else{
resolve(results[0]);
}
});
});
module.exports = {
getAllUser
};
Router:
router.get('/db',(req,res,next)=>{
getAllUser.then((result)=>{
console.log(result);
}).catch((e) => {
console.log(e);
});
});