UnhandledPromiseRejectionWarning: Reject an unhandled promise when processing certain cases with the question - javascript

I have this question that addresses a bunch of cases:
Your function must always return a promise
If data is not a number, return a promise rejected instantly and give the data "error" (in a string)
If data is an odd number, return a promise resolved 1 second later and give the data "odd" (in a string)
If data is an even number, return a promise rejected 2 seconds later and give the data "even" (in a string)
I typed the code for the question, but I got this error:
(node:6) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: data is not defined
(node:6) 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.
This is the code:
const job = new Promise((resolve, reject)=>{
if(isNaN(data)){
reject('erroe')
}
else if(isNaN(data) && data%2!=0){
setTimeout(function(){
resolve('odd')
} , 1000)
}
else {
setTimeout(function(){
reject('even')
}, 2000)
}
})
module.exports = job;

Here's what you can do in a concise way:
const job = data => new Promise((resolve, reject) =>
typeof(data) === "number"
? setTimeout(() => resolve(data % 2 ? 'odd' : 'even'), 1000)
: reject("error"))
job("s")
.then(result => console.log(result))
.catch(error => console.log(error));
job(5)
.then(result => console.log(result))
.catch(error => console.log(error))
job(2)
.then(result => console.log(result))
.catch(error => console.log(error))

Related

why does fetchmock restore give unmatched get?

I have written logic based on test cases already defined.Basically the tc checks for one server call below is the code.How do I modify my logic to make the tc pass?
this is test case:
it('there shall be only one server call in addFavourites()', (done) => {
fetchMock.get('http://localhost:3000/movies', moviesTestData);
fetchMock.get('http://localhost:3000/favourites', favouritesTestData);
script.getMovies()
.then(() => {
return script.getFavourites();
})
.then(() => {
fetchMock.restore();
fetchMock.post('http://localhost:3000/favourites', moviesTestData[1]);
return script.addFavourite(27621);
})
.then(() => {
expect(fetchMock.done()).to.equal(true);
done();
})
.catch((err) => {
expect(err).to.equal(null, err);
done();
});
});
this is the logic written.It basically makes call to movies,tries to get it,checks if the selected favourite exists and adds if its not there
function addFavourite(event) {
const id = event;
// eslint-disable-next-line consistent-this
// const self = this;
let favmovie = {};
let favmovies={};
//     let favmovie = {};
 return fetch('http://localhost:3000/movies')
.then(response =>{
if(response.status === 200)
{
return Promise.resolve(response.json());
}
else
// eslint-disable-next-line no-else-return
{
return Promise.reject(new Error('Unable to fetch the data'));
}
}).then(movies=>{
console.log('moviesssss',movies);
movies.forEach(movie => {
if(movie.id === id) {
 favmovie = movie;
}
return Promise.resolve(favmovie);
})
return fetch('http://localhost:3000/favourites')
.then(response =>{
if(response.status === 200)
{
return Promise.resolve(response.json());
}
else
// eslint-disable-next-line no-else-return
{
return Promise.reject(new Error('Unable to fetch the data'));
}
});
}).then(favmoves=>{
favmovies = favmoves;
}).then(()=>{
favmovies.filter(function(movie) {
if(movie.id === id) {
// eslint-disable-next-line no-alert
alert('Movie is already added to favourites');
}
});
}).then(()=>{
return fetch('http://localhost:3000/favourites', {
method: 'POST',
body: JSON.stringify( favmovie),
headers: {
'content-type': 'application/json'
}
})
.then(addedFav =>{
// console.log('addedFav',addedFav.json());
return Promise.resolve(addedFav.json());
}).then(resp=>{
const ul = document.getElementById('favouritesList');
const div = document.createElement('div');
const img = document.createElement('img');
img.setAttribute('src', resp.posterPath);
div.classList.add('moviecontent');
img.classList.add('image');
div.appendChild(document.createTextNode(resp.title));
div.appendChild(img);
div.appendChild(document.createTextNode(resp.overview));
ul.appendChild(div);
console.log('resp',resp);
});
}).catch(err =>{
return Promise.reject(new Error(null, err));
});
}
error is :
Unmatched GET to http://localhost:3000/movies
(node:59340) UnhandledPromiseRejectionWarning: AssertionError: Error: No fallback response defined for GET to http://localhost:3000/movies: expected [Error: No fallback response defined for GET to http://localhost:3000/movies] to equal null
at /Users/anushamuthyalampally/Stack Route/Assignment/javascript-movie-cruiser-assignment/test/script.spec.js:230:20
(node:59340) 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:59340) [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.
1) there shall be only one server call in addFavourites()
0 passing (2s)
1 failing
1) Movie Cruiser
there shall be only one server call in addFavourites():
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/Users/anushamuthyalampally/Stack Route/Assignment/javascript-movie-cruiser-assignment/test/script.spec.js)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)

Promise.all causes Jest to display UnhandledPromiseRejectionWarning

I have some code which calls Promise.all. It runs OK in the browser with no warnings in the console.
There are 3 functions f1, f2 & f3 all of which return a promise. The code looks like this
Promise.all([
f1(),
f2(),
f3()
]).then((values) => {
resolve({success: true})
}).catch(err => {
reject(err)
})
When I use Jest to test the file containing the above code I see this error.
(node:17177) 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: 18)
Is this the wrong way to code the above or is it a bug within Jest?
Here's the actual code that I'm using:
getDataFromDatabase() {
return new Promise((resolve, reject) => {
const assessmentUrl = `${this.assessmentUrl}`
http.get(assessmentUrl).then(response => {
if (response.data.record === null) {
Promise.all([
this._getPupilPlacement(),
this._getSurveyQuestions(),
this._getCompetencies()
]).then((values) => {
successState.pupilPlacement = values[0].pupilPlacement
successState.items = values[1].items
successState.formid = values[2].formid
successState.competencies = values[3].competencies
const panels = this.getPanels(values[3].competencies)
successState.panels = panels
successState.numPages = panels.length
successState.itemsAreOverridden = true
resolve(successState)
}).catch(err => {
reject(err)
})
}
else {
resolve(response.data.record)
}
})
})
}
Avoid the Promise constructor antipattern! You were forgetting to handle errors from the http.get(assessmentUrl) promise.
You should be writing
getDataFromDatabase() {
const assessmentUrl = `${this.assessmentUrl}`
return http.get(assessmentUrl).then(response => {
//^^^^^^
if (response.data.record !== null)
return response.data.record;
return Promise.all([
// ^^^^^^
this._getPupilPlacement(),
this._getSurveyQuestions(),
this._getCompetencies()
]).then(values => {
const panels = this.getPanels(values[3].competencies)
return {
// ^^^^^^
pupilPlacement: values[0].pupilPlacement,
items: values[1].items,
formid: values[2].formid,
competencies: values[3].competencies,
panels: panels,
numPages: panels.length,
itemsAreOverridden: true,
};
});
});
}
Explanation:
Calling reject will throw an error. If your top level promise doesn't catch it, then well it's an unhandled promise.
MDN Image src
Solution:
getDataFromDatabase().catch(err=>console.lor(err.message));
Example of a promise that rejects.:
function getDataFromDatabase(){
return Promise.reject(123);
}
getDataFromDatabase()
.then(data=>console.log("Success " + data))
.catch(err=>console.log("Error " + err));
Promise MDN doc
Future recommendation:
For every child promise you seem to be adding a .catch() which isn't needed. As long as somewhere higher up there is a catch, then the promise will be handled.

Promise rejection throws warning even if it's being caught later [duplicate]

This question already has answers here:
Prevent "Unhandled promise rejection" error
(3 answers)
Closed 4 years ago.
Example
class Foo {
private pro = new Promise(() => {
throw new Error();
});
public usePro() {
return this.pro.then(() => {});
}
}
let foo = new Foo();
setTimeout(() => {
foo.usePro().then(() => {
console.log("end.");
}).catch(() => {
console.log("error.");
})
}, 1000);
I understand that javascript can't know at runtime that someone will catch the error later, so how am I suppose to do in such a situation ?
Console
(node:39166) UnhandledPromiseRejectionWarning: error
(node:39166) 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:39166) [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.
error.
(node:39166) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
Errors should be caught wherever the Promise is used, even if that Promise is returned (and caught) by something else later. One option would be to assign to this.proValue a resolved object or a rejected object, depending on whether the original Promise resolves or rejects. Then, when usePro is called, check this.proValue and return either Promise.resolve(resolved) or Promise.reject(rejected). Using standard Javascript so this can be shown in a runnable snippet:
class Foo {
constructor() {
this.pro = new Promise(() => {
throw new Error('Problem!');
})
.then((resolved) => {
this.proValue = { resolved };
})
.catch((rejected) => {
this.proValue = { rejected };
});
}
usePro() {
const { resolved, rejected } = this.proValue;
if (resolved) return Promise.resolve(resolved);
else if (rejected) return Promise.reject(rejected);
}
}
const foo = new Foo();
setTimeout(() => {
foo.usePro().then(() => {
console.log("end.");
}).catch((e) => {
console.log("error caught. " + e);
})
}, 1000);
If you want to be able to call usePro before Foo's internal Promise has resolved (or rejected), then when usePro is called, construct and return a Promise that resolves once this.pro's Promise resolves (or rejects). unfortunately the code required is moderately more complicated:
class Foo {
constructor() {
this.callProms = [];
setTimeout(() => {
this.pro = new Promise(() => {
throw new Error('Problem!');
})
.then((resolved) => {
this.proValue = { resolved };
})
.catch((rejected) => {
this.proValue = { rejected };
})
.finally(() => {
console.log('internal promise finishing');
this.resolveCalls();
});
}, 1000);
}
resolveCalls() {
this.callProms.forEach((resolve) => {
resolve(this.getProValue());
});
}
getProValue() {
const { proValue } = this;
if (!proValue) return;
const { resolved, rejected } = proValue;
if (resolved) return Promise.resolve(resolved);
else if (rejected) return Promise.reject(rejected);
}
usePro() {
return this.getProValue()
|| new Promise((resolve) => {
this.callProms.push(resolve);
});
}
}
console.log('Starting');
const foo = new Foo();
// Immediate call of `usePro`:
foo.usePro().then(() => {
console.log("end.");
}).catch((e) => {
console.log("immediate error caught. " + e);
})
// Delayed call:
setTimeout(() => {
foo.usePro().then(() => {
console.log("end.");
}).catch((e) => {
console.log("delayed error caught. " + e);
})
}, 2000);
Great answer by CertainPerformance.
Let me add that in Node.js, you can also add an unhandledRejection listener on process:
process.on('unhandledRejection', reason => {
console.error({Error:reason})
process.exit(1);
});
You could use Promise.all to delay the resolving:
const delay = ms => new Promise(res => setTimeout(res, ms));
Promise.all([
foo.usePro(),
delay(1000)
]).then(() => {
console.log("end.");
}).catch(() => {
console.log("error.");
});
That way the .catch is directly attached, but the then callback is executed after the delay.

Chained promises won't catch an error

I'm trying to make promises work, and so far i've stumbled on this:
new Promise((resolve, reject) => {
setTimeout(() => {
return resolve()
}, 400)
}).then(new Promise((resolve, reject) => {
setTimeout(() => {
return reject('some error')
}, 100)
})).then(() => {
console.log('All promises resolved')
}).catch((err) => {
console.log('Error: ' + err)
})
My understanding is that this example should display Error: some error, with the first promise successfully resolving, and the second one throwing an error. But when i run this (in node 9.7, if that matters) i get this error:
(node:10102) UnhandledPromiseRejectionWarning: some error
(node:10102) 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:10102) [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.
All promises resolved
My .catch() doesn't seem to be working, is there a problem with it ?
You are actually passing promise, instead of function.
You should write your code like this:
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 400)
}).then(() => new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('some error'))
}, 100)
})).then(() => {
console.log('All promises resolved')
}).catch((err) => {
console.log('Error: ' + err)
})

expecting promised to resolve or reject doesn't properly fail a test with mocha and chai-as-promised

Using Mocha and chai-as-promised, I'm trying to test that my promised are being resolved and rejected properly. But the expect functions given by chai-as-promised aren't properly causing the tests to fail. Example:
test.js
const chai = require('chai')
chai.use(require('chai-as-promised'))
const expect = chai.expect
describe('foo', () => {
it('resolve expected', () => {
expect(new Promise((res,rej) => {res()})).to.be.fulfilled
})
it('resolve unexpected', () => {
expect(new Promise((res,rej) => {res()})).to.be.rejected
})
it('reject expected', () => {
expect(new Promise((res,rej) => {rej()})).to.be.rejected
})
it('reject unexpected', () => {
expect(new Promise((res,rej) => {rej()})).to.be.fulfilled
})
})
When I execute mocha test.js:
foo
✓ resolve expected
✓ resolve unexpected
(node:2659) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: expected promise to be rejected but it was fulfilled with undefined
(node:2659) [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.
✓ reject expected
✓ reject unexpected
(node:2659) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): AssertionError: expected promise to be fulfilled but it was rejected with undefined
4 passing (10ms)
You can see the assertion-errors seem to get thrown, but mocha doesn't pick them up. How can I get mocha to recognize the failures?
As we confirmed, and for future reference, the problem was that you did not return the assertion in each test.
it('reject expected', () => {
return expect(new Promise((res,rej) => {rej()})).to.be.rejected
})
it('reject unexpected', () => {
return expect(new Promise((res,rej) => {rej()})).to.be.fulfilled
})
This is why the tests passed but then later printed an "unhandled" promise when it did finally return. The return keyword informs mocha to wait for the async function to resolve/reject.
Alternatively with chai-as-promised library, you can try using chai.should and call .notify to indicate its 'done'. Like this:
const chai = require('chai');
chai.use(require('chai-as-promised'));
chai.should();
const expect = chai.expect;
describe('foo', () => {
it('resolve expected', () => {
expect(new Promise((res, rej) => { res(); })).to.be.fulfilled;
});
it('resolve unexpected', (done) => {
// expect(new Promise((res, rej) => { res(); })).to.be.rejected;
new Promise((res, rej) => { res(); }).should.be.rejected.and.notify(done);
});
it('reject expected', (done) => {
// expect(new Promise((res, rej) => { rej(); })).to.be.rejected;
new Promise((res, rej) => { rej(); }).should.be.rejected.and.notify(done);
});
it('reject unexpected', (done) => {
// expect(new Promise((res, rej) => { rej(); })).to.be.fulfilled;
new Promise((res, rej) => { rej(); }).should.be.fulfilled.and.notify(done);
});
});
This way mocha will recognize the test failure:
foo
√ resolve expected
1) resolve unexpected
√ reject expected
2) reject unexpected
2 passing (37ms) 2 failing
1) foo
resolve unexpected:
AssertionError: expected promise to be rejected but it was fulfilled with undefined
2) foo
reject unexpected:
AssertionError: expected promise to be fulfilled but it was rejected with undefined
Check chai-as-promised doc for further reference here
it ('creates images', async () => {
assert.equal(imageCount,1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(),imageCount.toNumber(),'id is correct')
assert.equal(event.hash,hash,'Hash is correct')
assert.equal(event.description,'Image Description','description is correct')
assert.equal(event.tipAmount,'0','tip amount is correct')
assert.equal(event.author, author, 'author is correct')
await decentragram.uploadImage('','Image description', { from: author }).should.be.rejected;
await decentragram.uploadImage('Image hash','', { from:author }).should.be.rejected;
})
facing the same issue here.But agree with [luke-stoward][1]
Solution: Add return
it ('creates images', async () => {
return
assert.equal(imageCount,1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(),imageCount.toNumber(),'id is correct')
assert.equal(event.hash,hash,'Hash is correct')
assert.equal(event.description,'Image Description','description is correct')
assert.equal(event.tipAmount,'0','tip amount is correct')
assert.equal(event.author, author, 'author is correct')
await decentragram.uploadImage('','Image description', { from: author }).should.be.rejected;
await decentragram.uploadImage('Image hash','', { from:author }).should.be.rejected;
})

Categories