Destructuring and property shorthand error - javascript

I am new to node, and I was working with destructuring. I wanted to get the body property from the response of an weather-api and destructure it. The code is working fine when I am connected with internet but when I disconnect the internet the code crash and throws the error.
Here is the code I have written
```const request = require('request')
const geocode = (address, callback)=>{
const url = "https://api.mapbox.com/geocoding/v5/mapbox.places/" +encodeURIComponent(address)+ ".json?access_token=theKeyHere"
request({url, json: true}, (error, {body})=>{
if(error){
callback('Uh! Oh, Unable to connect with location service', undefined )
} else if (body.features.length ===0 || body.message){
callback(`Uh! Oh, Can't find location. Try another search`, undefined)
} else {
callback(undefined, {
latitude: body.features[0].center[1],
longitude: body.features[0].center[0],
location_Name: body.features[0].place_name
})
}
})
} ```
The error which I am getting
request({url, json: true}, (error, {body={}})=>{
^
TypeError: Cannot read property 'body' of undefined
at Request._callback (F:\nodejs\weatherApp\utils\geocode.js:6:41)
at self.callback (F:\nodejs\weatherApp\node_modules\request\request.js:185:22)
at Request.emit (events.js:315:20)
at Request.onRequestError (F:\nodejs\weatherApp\node_modules\request\request.js:877:8)
at ClientRequest.emit (events.js:315:20)
at TLSSocket.socketErrorListener (_http_client.js:426:9)
at TLSSocket.emit (events.js:315:20)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21)

The problem is that when there's an error, you're still trying to destructure the data:
request({url, json: true}, (error, {body={}})=>{
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^
But in the error case, the data hasn't arrived, you've gotten undefined instead. You can't destructure undefined or null.
You have two options:
Use a plain parameter, and then destructure once you know you don't have an error:
request({url, json: true}, (error, response)=>{
if (error) {
// ...
return;
}
const {body = {}} = response;
// ...
});
Provide a default for the parameter as a whole, not just body:
request({url, json: true}, (error, {body={}} = {})=>{
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^
// ...
});
That way, if you're passed undefined, you'll destructure {} instead. And since you're already defaulting body if it doesn't exist on the object, that default will kick in.

the issue is, when you're not connected to the internet, or you dont get the expected response structure, the second argument of that function is undefined. so you're essentially trying to do this:
undefined.body which, of course, is wrong
you can do 2 things to fix it:
// - this will guarantee that the second argument will always default to
// an empty object. this way, you will not get an error
(error, { body={} } = {}) => {
or
(error, response) => {
let body = {};
if (response) body = response.body || {};
}

Related

listener argument must be of type Function error using socket io

With the below function using socket io to join the connection for making workspace getting error of
The "listener" argument must be of type Function.
How to solve this error, below I have pasted the entire error, I'm new to socketio what is the best way to feed the requirements as expected by the io.on() function.
export const roomJoin = (socket, io, msg) => {
if (msg.room_id) {
socket.join(msg.room_id, () => {
io.on('room_join', function(socket){
socket.emit('request',{ status: true, msg: "room join", room_id: msg.room_id });
return
});
})
} else {
socket.emit('room_join', { status: false, message: "Invalid/Missing data" });
}
}
Getting this error
--------------------->connected EUFilhEfZmuXKjsIAAAA
------------------------->workspace_room_join {
msg: {
workspace_id: '5e29d571495f2e0043d2ddef',
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlMjlkNTcxNDk1ZjJlMDA0M2QyZGRlZiIsImVtYWlsIjoiZmFyaGFuNzAxMUBob3RtYWlsLmNvbSIsImlhdCI6MTU3OTk3ODMxMCwiZXhwIjoxNTgwNTgzMTEwfQ.ZlvVanwTMGcD5sXp0-T-W3VImSGhus5i5aDem1-hUTQ'
}
}
events.js:64
throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type Function. Received type undefined
at checkListener (events.js:64:11)
at _addListener (events.js:226:3)
at Namespace.addListener (events.js:284:10)
at Server.<computed> [as on] (/Users/user/Documents/weaverse-sockets-version2/node_modules/socket.io/lib/index.js:505:29)
at /Users/user/Documents/weaverse-sockets-version2/dist/controller/roomJoin.js:62:16
at /Users/user/Documents/weaverse-sockets-version2/node_modules/socket.io/lib/socket.js:255:11
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
code: 'ERR_INVALID_ARG_TYPE'
}

Node.Js Slack App Https request 'Uncaught Exception: Converting circular structure to JSON'

I am trying to create a slack app, using stdlib that can take a simple text argument and then use that information to make an https request to a url and get a json response back. However, when I try to make this request and output the string to slack as a text response, I get the following error:
Critical Error: TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at Domain.criticalExecution.run ([eval]:86:45)
at Domain.run (domain.js:242:14)
at callback ([eval]:66:23)
at func.index.apply.params.concat ([eval]:199:51)
at module.exports (/var/task/functions/commands/price.js:23:3)
at Domain.functionExecution.run ([eval]:197:22)
at Domain.run (domain.js:242:14)
at process.nextTick ([eval]:196:27)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
Now, I can't see anywhere in the response json that makes it cyclical, since it is just a text response, I don't add to it, so it confuses me.
Below is the source code:
module.exports = (user, channel, text = '', command = {}, botToken = null, callback) => {
callback(null, {
response_type: 'in_channel',
text: getString()
});
};
function getString() {
return getNasaData('DEMO_KEY');
}
function getNasaData(key = 'DEMO_KEY', callback) {
return https.get({
host: 'api.nasa.gov',
path: '/planetary/apod?api_key=${key}'
}, (response) => {
let body = '';
response.on('data', (data) => {
body += data;
});
response.on('end', () => {
let parsed = JSON.parse(body);
callback({
copyright: parsed.copyright,
date: parsed.date
});
});
});
};
I've looked around for solutions and its unclear what would cause this exception other than a cyclical reference. Perhaps it is to do with the callbacks I'm using in the two methods?
Thank you for any help.

How to solve Unhandled rejection TypeError: Converting circular structure to JSON for jwt.sign

When I try to create a token for a user like in this code :
const jwt = require('jsonwebtoken');
const passport = require('passport');
const Patient = require('../models').Patient;
module.exports = {
retrieve(req, res) {
return Patient
.find({
where: {
email: req.body.email,
}
})
.then(patient => {
if (!patient) return res.json({
success: false,
msg: 'Patient not found'
});
const result = Patient.build().verifyPassword(req.body.password, patient.password);
if (!result) {
return res.json({
success: false,
msg: 'wrong password'
});
} else {
const token = jwt.sign(patient, secret, {
expiresIn: 604800 // 1 week
});
return res.status(201).send(patient);
}
})
},
//
};
I get this error :
Unhandled rejection TypeError: Converting circular structure to JSON
at Object.stringify (native)
at toString (/home/omarou/Documents/Projet/PharmaLiv/node_modules/jws/lib/tostring.js:9:15)
at jwsSecuredInput (/home/omarou/Documents/Projet/PharmaLiv/node_modules/jws/lib/sign-stream.js:12:34)
at Object.jwsSign [as sign] (/home/omarou/Documents/Projet/PharmaLiv/node_modules/jws/lib/sign-stream.js:22:22)
at Object.module.exports [as sign] (/home/omarou/Documents/Projet/PharmaLiv/node_modules/jsonwebtoken/sign.js:146:16)
at Model.Patient.find.then.patient (/home/omarou/Documents/Projet/PharmaLiv/server/controllers/patients.js:27:39)
at Model.tryCatcher (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/home/omarou/Documents/Projet/PharmaLiv/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:651:20)
at tryOnImmediate (timers.js:624:5)
controllers/patients.js:27:39 refer to the method jwt.sign on my code
It tells that it's coming from the jwt.sign method
Anyone can tell me what's the matter ?
"circular structure" means that something in the object you are trying to return contains a reference to itself or to a thing that it is contained in. This sort of structure can't easily be serialized.
It looks like the problem must be in the structure of your Patient object itself. You will need to simplify it for signing or sending over the wire
I found the mistake
the object patient has too much methods that make the circular structure.
so I created a variable playload that contains the variable that I need for authentication.
const payload = {email: patient.username, password: patient.password};
const token = jwt.sign(payload, secret, {
expiresIn: 604800 // 1 week
});
it works now thanks to #andrewMcGuinness for his answer :)

Error when run .js file with Node js "TypeError: Cannot read property 'render' of undefined"

I am writing a node program, but I meet an error when run following code (node test.js):
var pdf = require('html-pdf');
var options = {format: 'Letter'};
//console.log(" debug");
function Topdf(req,res) {
var info = require("./info.json");
res.render("./template.html",{ info : info,}, function (err, HTML) {
pdf.create(HTML, options).toFile('./downloads/employee.pdf', function (err, result) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
})
})
}
Topdf();
failed log:
res.render("./template.html",{ info : info,}, function (err, HTML) {
^
TypeError: Cannot read property 'render' of undefined
Could anyone please help? What is problem here?
Well, you are defining a function with 2 parameters (which should not start with a capital letter, BTW, since it is not a function to be called as a constructor), the second one being res
function Topdf (req, res) {
...
}
But you are invoking it with no arguments:
Topdf();
So req and res are undefined, so you cannot read the property render of undefined. The error message is quite explicit...

Dynamo DB getItem with node js throwing error

I am new to Javascript and DynamoDB. I am trying to perform getitem using aws-sdk for javascript in nodejs. primary index of Dynamo table Cars is "name" a string.
var AWS = require('aws-sdk');
AWS.config.region='eu-west-1';
var db = new AWS.DynamoDB();
var params = {
TableName : 'Cars',
Key : {
"name" : {
"S" : "Volkswagen Dasher"
},
}
}
db.getItem(params, function(err, data) {
if (err) {
console.log(err); // an error occurred
}
else {
console.log(data); // successful response
}
return next();
});
On running the above .js file I am getting the following error.
ubuntu#ubuntu:~/node$ node getItem.js
{}
/home/ubuntu/node_modules/aws-sdk/lib/request.js:30
throw err;
^ ReferenceError: next is not defined
at Response.<anonymous> (/home/ubuntu/node/getItem.js:21:10)
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:353:18)
at Request.callListeners (/home/ubuntu/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/home/ubuntu/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/home/ubuntu/node_modules/aws-sdk/lib/request.js:595:14)
at Request.transition (/home/ubuntu/node_modules/aws-sdk/lib/request.js:21:10)
at AcceptorStateMachine.runTo (/home/ubuntu/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /home/ubuntu/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:37:9)
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:597:12)
Plz help me out. Cheers!
Glad to see you're giving DynamoDB a try! I'm not really sure I understand the context of your code, but if your goal is to make a simple GetItem call, you don't need the 'return next()' statement. Given javascript's event driven nature, these callbacks are asynchronous and don't really "return" anything. Instead, you should inspect the response (data) and perform an action accordingly.
I.E.
dynamoDB.getItem(params, function(err, data) {
if (data) {
doSomethingWithItem(data.Item);
}
});
Also, if you're just starting out I would recommend taking a look at the document-js-sdk which a wrapper on top of the original SDK to allow you to use literals such as "string" instead of {S: "string"}.

Categories

Resources