Nodejs. Unhandled Promise Rejection - javascript

I am trying to test some functionality. Inside the routes.js file, i placed this code:
async function getPic(arg) {
const browser = await puppeteer.launch(/*{headless: false}*/);
const page = await browser.newPage();
await page.goto(arg);
await page.setViewport({width: 1000, height: 500})
await page.screenshot({path: 'pic.png'});
await broswer.close();
}
I read about async/await (it is the first time i use it). Though i get an error message and the code does not work:
(node:5896) UnhandledPromiseRejectionWarning: Error: Navigation Timeout Exceeded
: 30000ms exceeded
at Promise.then (C:\...\node_modules\puppeteer\lib\NavigatorWatcher.js:73:21
)
at <anonymous>
(node:5896) 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:5896) [DEP0018] DeprecationWarning: Unhandled promise rejections are depre
cated. In the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.
Unfortunately i do not know what this means. I found out a similar question on stackoverflow here:
NodeJS Unhandled Promise Rejection
But unfortunately does not make things clear for me on how to solve this error.
When i tested this snippet of code in a standalone node environment - meaning just this code without anything else, as i do in my project, then somehow it works.
When i place this function inside my routes.js file, and then invoke the function when a post event happens then i get the error.
Here is the code that invokes this function:
app.post('/sc', function(req, res){
var url = req.body.convo
console.log(url)
getPic(url);
})

You should use await before call async function and wrapp await call into try catch construction.
app.post('/sc', async (req, res) => {
const url = req.body.convo
try {
var picture = await getPic(url);
//some logic or render response
} catch (error){
//here you should handle error
}
})

You need to await getPic(url);.
Also you have browser misspelled in await broswer.close();

Related

What is the difference between throwing inside .then block or within async await block?

I get this error:
(node:9868) UnhandledPromiseRejectionWarning: #<Object>
(node:9868) 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:9868) [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 wrapping the create method with express error handler that looks like this:
export const errorHandler = (callback: any) => {
return (req: Request, res: Response, next: NextFunction) => {
callback(req, res, next).catch(next);
};
};
when I try to do this:
async create(entity: T){
this._model
.findOne({ name: (entity as any).name })
.then((res) => {
if (res) {
throw Exceptions.ENTITY_EXISTS; // doesnt work
}
})
}
however when I change it to be async await it works fine
async create(entity: T) {
const res = await this._model.findOne({ name: (entity as any).name });
if (res) throw Exceptions.ENTITY_EXISTS;
}
Also when I tried to do instead of throw Promise.reject(Exceptions.ENTITY_EXISTS) it threw the same error.
Can someone explain me the differences between these three, and also why only the async await is working?
The difference is indeed where the throw happens. In the working version, it makes the promise returned by create() to settle as rejected.
In the non-working version it makes the promise returned by .then() to settle as rejected. However this promise is not the one returned by create(), and so even if you correctly handle a rejection on create()... that doesn't handle the rejection that happened on the then() promise. They are not connected, and so you don't handle that rejection.
To fix the first version, make sure to return the promise returned by .then():
create(entity: T){
return this._model
// ^^^^^^
.findOne({ name: (entity as any).name })
.then((res) => {
if (res) {
throw Exceptions.ENTITY_EXISTS; // doesnt work
}
});
}
NB: Although you could keep async before the function, it really is not so useful if you don't use await and return a promise.
NB2: Because of this missing return, the create function actually returned a promise that resolved immediately... so it was never awaiting the database query.

puppeteer throw error "UnhandledPromiseRejectionWarning" and crash

I want to take a screenshot of a webpage, but no matter what I do puppeteer always crashes。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto('https://www.google.com/');
await page.screenshot({path: 'screenshot/example.png'});
await page.waitFor(5 * 1000);
await browser.close();
})();
I saved the above code as web.js, and executed node web.js in cmd. It crashed 2 seconds after the Chrome window appeared, and the page did not load。
(node:27064) UnhandledPromiseRejectionWarning: #
(Use node --trace-warnings ... to show where the warning was created)
(node:27064) 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:27064) [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've to add an error handler to your promise.
As soon your promised (in this case your async function) throws any error, it reaches the execution root, which in nodejs will cause the app to "crash".
Just call your function like this:
(async () => {
/* your code here */
})().catch(error => { console.error("Something bad happend...", error); });
``´

Using loop with async/await inside loop + nodejs

Hello in my nodejs api i need fetch data inside the loop and then again need to do a loop and save a data in another table how should i achive that?
Here is some snippet that i have tried but not succeeded for the same
async myAPIname(){
let _this = this;
try {
const bets = await Bet.find({gameId:ObjectId(request.matchId)}).lean()
bets.map(async (bet) => {
let Users = await Users.findOne({_id:ObjectId(element.userId)}).lean();
Users.parentTree.map(async (user) => {
console.log(user);
// also over here based on the some calculation need to save the data in another table
})
})
} catch (error) {
_this.res.send({ status: 0, message: error });
}
}
Also in above snipped tried with foreach loop as well but not succeeded
and error from above spinet like this:
(node:30886) UnhandledPromiseRejectionWarning: ReferenceError: Cannot access 'Users' before initialization
at /var/www/html/api/app/controllers/SomeController.js:228:30
at Array.map (<anonymous>)
at SomeController.myAPIname (/var/www/html/api/app/controllers/SomeController.js:227:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:30886) 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:30886) [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.
(node:30886) UnhandledPromiseRejectionWarning: TypeError: Assignment to constant variable.
at /var/www/html/api/app/controllers/SomeController.js:220:27
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:30886) 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: 2)
Any Help will really appreciated
I can see two problems:
firstly the await inside a map call doesn't work like you think. It will work fine in a for-of loop but not in a map, foreach etc.
https://zellwk.com/blog/async-await-in-loops/ has a good an explanation as anywhere.
Secondly where you are calling let Users = Users.findOne, the compiler thinks that Users on the left hand side of the assignment is the same as the Users on the right hand side so it complains that when its calling Users.findOne, Users isn't initialised.
to use asynchronous handling with Array.prototype.map() you have to wrap it with Promise.all() and wait for it to fulfill.
!! however notice that iterations are executed in asynchronous way, not waiting for previous iteration to settle.
const sleep = async (time = 3000) => new Promise(resolve => setTimeout(resolve, time));
(async () => {
const array = [1,3,4,2];
console.log('start', array);
const mapped =await Promise.all(array.map(async e => {
await sleep(e * 1000);
console.log(e);
return `done for ${e}`;
}));
console.log('end', mapped);
})();

trying to use .then() in my server side script which uses node js but i get an error [duplicate]

For learning Angular 2, I am trying their tutorial.
I am getting an error like this:
(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) 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 went through different questions and answers in SO but could not find out what an "Unhandled Promise Rejection" is.
Can anyone simply explain me what it is and also what Error: spawn cmd ENOENT is, when it arises and what I have to check to get rid of this warning?
The origin of this error lies in the fact that each and every promise is expected to handle promise rejection i.e. have a .catch(...) . you can avoid the same by adding .catch(...) to a promise in the code as given below.
for example, the function PTest() will either resolve or reject a promise based on the value of a global variable somevar
var somevar = false;
var PTest = function () {
return new Promise(function (resolve, reject) {
if (somevar === true)
resolve();
else
reject();
});
}
var myfunc = PTest();
myfunc.then(function () {
console.log("Promise Resolved");
}).catch(function () {
console.log("Promise Rejected");
});
In some cases, the "unhandled promise rejection" message comes even if we have .catch(..) written for promises. It's all about how you write your code. The following code will generate "unhandled promise rejection" even though we are handling catch.
var somevar = false;
var PTest = function () {
return new Promise(function (resolve, reject) {
if (somevar === true)
resolve();
else
reject();
});
}
var myfunc = PTest();
myfunc.then(function () {
console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
console.log("Promise Rejected");
});
The difference is that you don't handle .catch(...) as chain but as separate. For some reason JavaScript engine treats it as promise without un-handled promise rejection.
This is when a Promise is completed with .reject() or an exception was thrown in an async executed code and no .catch() did handle the rejection.
A rejected promise is like an exception that bubbles up towards the application entry point and causes the root error handler to produce that output.
See also
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
Promises can be "handled" after they are rejected. That is, one can call a promise's reject callback before providing a catch handler. This behavior is a little bothersome to me because one can write...
var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });
... and in this case, the Promise is rejected silently. If one forgets to add a catch handler, code will continue to silently run without errors. This could lead to lingering and hard-to-find bugs.
In the case of Node.js, there is talk of handling these unhandled Promise rejections and reporting the problems. This brings me to ES7 async/await. Consider this example:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
let temp = await tempPromise;
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
await changeClothes("warm");
} else {
await changeClothes("cold");
}
await teethPromise;
}
In the example above, suppose teethPromise was rejected (Error: out of toothpaste!) before getRoomTemperature was fulfilled. In this case, there would be an unhandled Promise rejection until await teethPromise.
My point is this... if we consider unhandled Promise rejections to be a problem, Promises that are later handled by an await might get inadvertently reported as bugs. Then again, if we consider unhandled Promise rejections to not be problematic, legitimate bugs might not get reported.
Thoughts on this?
This is related to the discussion found in the Node.js project here:
Default Unhandled Rejection Detection Behavior
if you write the code this way:
function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
return Promise.resolve(tempPromise)
.then(temp => {
// Assume `changeClothes` also returns a Promise
if (temp > 20) {
return Promise.resolve(changeClothes("warm"));
} else {
return Promise.resolve(changeClothes("cold"));
}
})
.then(teethPromise)
.then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}
When getReadyForBed is invoked, it will synchronously create the final (not returned) promise - which will have the same "unhandled rejection" error as any other promise (could be nothing, of course, depending on the engine). (I find it very odd your function doesn't return anything, which means your async function produces a promise for undefined.
If I make a Promise right now without a catch, and add one later, most "unhandled rejection error" implementations will actually retract the warning when i do later handle it. In other words, async/await doesn't alter the "unhandled rejection" discussion in any way that I can see.
to avoid this pitfall please write the code this way:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
var clothesPromise = tempPromise.then(function(temp) {
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
return changeClothes("warm");
} else {
return changeClothes("cold");
}
});
/* Note that clothesPromise resolves to the result of `changeClothes`
due to Promise "chaining" magic. */
// Combine promises and await them both
await Promise.all(teethPromise, clothesPromise);
}
Note that this should prevent any unhandled promise rejection.
"DeprecationWarning: Unhandled promise rejections are deprecated"
TLDR: A promise has resolve and reject, doing a reject without a catch to handle it is deprecated, so you will have to at least have a catch at top level.
In my case was Promise with no reject neither resolve, because my Promise function threw an exception. This mistake cause UnhandledPromiseRejectionWarning message.
I was seeing this when I had a util file with a Promised API call, a component that calls it but wasn't explicitly handling the .catch, and a Jest that was mocking up a Promise.reject:
fetchStuff.mockImplementationOnce(() => Promise.reject(new Error('intentional fail')));
Furthermore, this was poisoning my mock, so that even though I was calling jest.resetAllMocks() before each test, the very next test would try render and that render would call the API, and it would fail. The test after would be back to a good state. I could swap around the order of my tests to prove that it would always poison the next render.
I tried handling the error in the API, but didn't succeed. I tried handling in my Jest mock, but that didn't work, either. What I ended up having to do was explicitly handle the .catch in my component.
I had faced a similar issue with NodeJS, where the culprit was a forEach loop. Note that forEach is a synchronous function (NOT Asynchronous). Therefore it just ignores the promise returned.
The solution was to use a for-of loop instead:
Code where I got the error:
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()
is as follows:
permissionOrders.forEach( async(order) => {
const requestPermissionOrder = new RequestPermissionOrderSchema({
item: order.item,
item_desc: order.item_desc,
quantity: order.quantity,
unit_price: order.unit_price,
total_cost: order.total_cost,
status: order.status,
priority: order.priority,
directOrder: order.directOrder
});
try {
const dat_order = await requestPermissionOrder.save();
res.json(dat_order);
} catch(err){
res.json({ message : err});
}
});
Solution for the above issue is as follows:
for (let order of permissionOrders){
const requestPermissionOrder = new RequestPermissionOrderSchema({
item: order.item,
item_desc: order.item_desc,
quantity: order.quantity,
unit_price: order.unit_price,
total_cost: order.total_cost,
status: order.status,
priority: order.priority,
directOrder: order.directOrder
});
try {
const dat_order = await requestPermissionOrder.save();
res.json(dat_order);
} catch(err){
res.json({ message : err});
}
};
Try not closing the connection before you send data to your database. Remove client.close(); from your code and it'll work fine.
When I instantiate a promise, I'm going to generate an asynchronous function. If the function goes well then I call the RESOLVE then the flow continues in the RESOLVE handler, in the THEN. If the function fails, then terminate the function by calling REJECT then the flow continues in the CATCH.
In NodeJs are deprecated the rejection handler. Your error is just a warning and I read it inside node.js github. I found this.
DEP0018: Unhandled promise rejections
Type: Runtime
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.

`NoSuchSessionError: invalid session id` when using selenium, even though application is working fine

Context and info:
I recently made a simple script that logs into a exterior website and gets some data. The purpose of this script was to get a students grades and then turn it into plottable data. To make the process of getting the data much easier I used the npm library: selenium-webdriver. The reason I used that library instead of request (for example) is because I need to login, and so that I don't get cross origin error (and yes I would get a cross origin error because my server is already connected to a front end app). Note that all of my code is inside an async function and that it is being called like a promise would (meaning that it is being called with a .then and not with a await inside of an async function.).
The issue:
The script works perfectly giving me the exact results I want, but I am still getting an error. This error is confusing to me because of twofold: first because all of my code is in a try block with a catch attached as well as having a .catch() where it is called; and second the error is logged after the function has resolved.
The error message:
(node:17908) UnhandledPromiseRejectionWarning: NoSuchSessionError: invalid session id
(Driver info: chromedriver=73.0.3683.68
(47787ec04b6e38e22703e856e101e840b65afe72),platform=Windows NT 10.0.17134 x86_64)
at Object.checkLegacyResponse (C:\Users\Redacted\Desktop\Application\Code\node_modules\selenium-webdriver\lib\error.js:585:15)
at parseHttpResponse (C:\Users\Redacted\Desktop\Application\Code\node_modules\selenium-webdriver\lib\http.js:533:13)
at Executor.execute (C:\Users\Redacted\Desktop\Application\Code\node_modules\selenium-webdriver\lib\http.js:468:26)
at processTicksAndRejections (internal/process/next_tick.js:81:5)
(node:17908) 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:17908) [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 code:
'use strict'
const {Builder, By, Key, until, Capabilities} = require('selenium-webdriver')
const Chrome = require('selenium-webdriver/chrome')
exports.simpleGradebookGetGrades = async function(username, password) {
const driver = new Builder().forBrowser('chrome').withCapabilities(Capabilities.chrome()).setChromeOptions(new Chrome.Options().addArguments('--remote-debugging-port=25470')).build()
try {
let retval = []
await driver.get('https://simplegradebook.ca/gradebook/login.php')
async function login(username, password) {
await driver.findElement(By.name('userid')).sendKeys(username)
await driver.findElement(By.name('password')).sendKeys(password)
await driver.findElement(By.name('login')).click()
await driver.wait(until.titleMatches(/.{20,}/))
return
}
await login(username, password)
for(let i of Object.keys(await driver.findElements(By.name('viewclasses')))) {
await driver.wait(until.elementsLocated(By.name('viewclasses')));
(await driver.findElements(By.name('viewclasses')))[i].click()
await driver.wait(until.elementLocated(By.tagName('tbody')))
retval.push(await driver.findElement(By.tagName('tbody')).getText())
await driver.get('https://simplegradebook.ca/gradebook/login.php')
login(username, password)
}
return retval
} catch(err) {
console.log(err)
} finally {
await driver.quit()
}
}
exports.simpleGradebookGetGrades('Redacted', 'Redacted').then(result => {
console.log(result)
}).catch(err => {
console.log(err)
})
My question:
Why is the error occuring? How can I remove or Ignore this error? Why is my catch block not catching this error?
Additional info:
Node version: 11.8.0
Selenium-webdriver version: 4.0.0-alpha.1
Do any of the errors go away if you define your driver with the following option for Chrome?
const chrome = require('selenium-webdriver/chrome')
const webdriver = require('selenium-webdriver')
let options = new chrome.Options()
let nextPort = 9222 //for example
options.addArguments(["--remote-debugging-port=" + nextPort])
let driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.setChromeOptions(options)
.build()

Categories

Resources