How to fetch data from response._body in proper way? - node.js

So starting first my nodejs server sends this as a response
"["name1","name2","name3"]"
but my angular 2 code for service is
return this.http.get(this.config.apiUrl + '/folder').map((response:Response)=> {
response.json();
console.log(response); }
How do I fetch the array?
If I use response._body there will be an error in npm start stating "._body undefined", so I make it as a comment then after npm start I reverse back, I know it is not proper way. Here is the console.log of above service code
Response
headers: Headers
ok:true
status:200
statusText:"OK"
type:2
url:"http://localhost:4000/folder"
_body:"["name1","name2","name3"]"
__proto__:Body
The main problem is to fetch in component in an array
Here, is the code I am trying
this.photoService.getAllfolder().subscribe(
data => {
console.log(data);
},
error => {
console.log(error);
});

You are missing a return statement in your mapping. Also if you then want to have the console log, you need to change the order. Your code should therefore look like this:
return this.http.get(this.config.apiUrl + '/folder')
.map((response:Response)=> {
console.log(response);
return response.json(); // return
}

you can get data in lot of ways easy way was response["_body"] or response.text()
return this.http.get(this.config.apiUrl + '/folder').map((response)=> {
response["_body"];
console.log(response); }

Related

Getting "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" while using Axios

I am trying to use different Axios calls to get some data from a remote server. One by one the calls are working but as soons as I call them directly after each other its throwing the error message about the headers. I did some research already and I guess it has sth to do that there the headers of the first call gets in the way of the second call. That is probably a very simplematic description of the problem but I am new to node js and the way those axios calls are working.
This is an example of one of my Api calls:
app.get('/api/ssh/feedback', function(req, res){
conn.on('ready', function(){
try {
let allData = {}
var command = 'docker ps --filter status=running --format "{{.Names}}"'
conn.exec(command, function(err, stream){
if (err) throw console.log(err)
stream.on('data', function(data){
allData = data.toString('utf8').split('\n').filter(e=>e)
return res.json({status: true, info: allData})
})
stream.on('close', function(code){
console.log('Process closed with: ' + code)
conn.end()
})
stream.on('error', function(err){
console.log('Error: ' + err)
conn.end()
})
})
} catch (err) {
console.error('failed with: ' + err)
}
}).connect(connSet)
})
I am using express js as a middleware and the shh2 package to get the connection with the remote server. How I mentioned before the call is working but crashes if it is not the first call. I am able to use the api again after I restart the express server.
This is how I am calling the api through axios in my node js frontend:
getNetworkStatus(e){
e.preventDefault()
axios.get('/api/ssh/network').then(res =>{
if(res.data.status){
this.setState({network_info: 'Running'})
this.setState({network: res.data.info})
} else {
this.setState({network_info: 'No Network Running'})
this.setState({network: 'No Network detected'})
}
}).catch(err => {
alert(err)
})
}
I would be really grateful for any help or advice how to solve this problem. Thanks to everyone who spends some time to help me out.
There are two issues in the code you've provided:
You are making assumptions about 'data' events. In general, never assume the size of the chunks you receive in 'data' events. You might get one byte or you might get 1000 bytes. The event can be called multiple times as chunks are received and this is most likely what is causing the error. Side note: if the command is only outputting text, then you are better off using stream.setEncoding('utf8') (instead of manually calling data.toString('utf8')) as it will take care of multi-byte characters that may be split across chunks.
You are reusing the same connection object. This is a problem because you will continue to add more and more event handlers every time that HTTP endpoint is reached. Move your const conn = ... inside the endpoint handler instead. This could also be causing the error you're getting.

How to check states after sending request in server?

I am trying to check states after sending requests to the server by using axios. I designed the server that if you submitted the form with an empty input, you will get an error. If you can see in the code, I have tried to check the states in finally block but it is not working properly. Like when I submitted the form initially with no inputs, the console log displays no errors and when I try to submit the form with the inputs, it doesn't display anything in the console. I just want to check if there is an error with the request because I want to run a function between them.
The server I used is live and running and you can get the data/submitted form by changing the URL into /getUser
Code here: https://codesandbox.io/s/quizzical-danny-dv1l7?file=/src/App.js
It doesnt works like that.
const [error, setError] = useState("");
error is the initial value (empty string). In dont realy knows how useState is working but, error is a string so it s a value, not a reference. There is no way this variable get updated it the finaly block.
The simple answer is you are setting your state inside the function and then trying to read it as your "current state". Try this instead...
const handleSubmit = async (e) => {
e.preventDefault();
try {
await axios.post("https://testing-name-app.herokuapp.com/create", {
first,
last
});
} catch (error) {
console.log("error found");
return setError(error.response.data.errorMessage);
}
// be CAREFUL with this pattern! This just means the request came back
// with no errors, but there may be a message from your call that
// contained an error from your db/server etc
return console.log("no errors");
};
And here's a way to quickly see what's going on in your call...
const handleSubmit = async (e) => {
e.preventDefault();
let res
try {
res = await axios.post("https://testing-name-app.herokuapp.com/create", {
first,
last
});
} catch (error) {
res = error
console.log("error found");
setError(error.response.data.errorMessage);
}
finally {console.log('res: ', res)}
};

Recommended pattern to page through API response until exhausted?

I'm new to Node and the async programming model. I'm having problems dealing with a simple requirement that seems pretty basic in synchronous environments: paging through an API response until the response is empty.
More specifically, the API, on a successful call, will return data and a status of 200 or 206 (partial content). If I see the 206 response, I need to keep making calls to the API (also sending a page query param that I increment each time) until I see the 200 response.
In a synchronous language, the task will be a piece of cake:
// pseudocode
data = []
page = 1
do {
response = api.call(page)
data.append(response.data)
page++
} while (response != 200)
return data
Now, in Node, for a single api call, code like this will work:
// fire when '/' has a GET request
app.get('/', (req, res) => {
axios.get('https://api.com/v1/cats')
.then(response => {
// now what??
});
});
});
See the //now what?? comment? That's the point where I'm wondering how to proceed. I came across this somewhat-relevant post but am not able to convert this to a format that will work for me in Node and Axios.
Is it enough to just wrap the axios code in a separate function? I don't think so, because if I do this:
function getData(pageNum) {
axios.get('https://api.com/v1/cats')
.then(response => {
// now what??
});
});
}
I can't rely on a return value because as soon axios.get() gets executed, the function will be over. I can call getData() again after I get the first response, but then, suppose I want to return all the data from these multiple calls as the HTTP response from my Express server . . . how do I do that?
I hope I will not get downvoted for laziness or something. I've really looked around but not found anything relevant.
First, a counter-question: Is the data set so big that you need to worry about using up all the memory? Because if so then it will take more work to structure your code in a way that streams the data all the way through. (In fact I'm not even sure whether express allows streaming... you are using express aren't you?)
From the axios documentation, it looks like response is a readable stream which provides the response body. So reading it is also an asynchronous task. So you should write a function that does that. See the "Stream" page of the nodejs docs for more details. Or I could be persuaded to help with that too, time permitting. But for now, I'll assume you have a function readResponse, which takes an axios response object as an argument and returns a promise, and the promise resolves to an object such as { statusCode: 206, result: ['thing1', 'thing2'] }. I'll also assume that your goal is to get all the result arrays and concatenate them together to get e.g. ['thing1', 'thing2', 'thing3', 'thing4', 'thing5', 'thing6'].
You could write a self-calling version of your getData function. This will retrieve all data from a given page onwards (not just the page itself):
function getData(pageNum) {
axios.get('https://api.com/v1/cats' + (pageNum ? '?page=' + pageNum) : '')
.then(readResponse)
.then(function(parsedResponse) {
if(parsedResponse.statusCode == 200) {
return parsedResponse.result;
} else if(parsedResponse.statusCode == 206) {
return getData(pageNum + 1).then(function(laterData) {
return parsedResponse.result.concat(laterData);
});
} else {
// error handling here, throw an exception or return a failing promise.
}
});
});
}
Then, to get all data, just call this function with pageNum = 0:
// fire when '/' has a GET request
app.get('/', (req, res) => {
getData(0)
.then(function(results) {
// results is now the array you want.
var response = JSON.stringify(results); // or whatever you're doing to serialise your data
res.send(response);
});
});

Node.js DNS Lookup scope error? (POST request)

I'm making a DNS Lookup API using Node.js and Express.js framework such that when it sends a POST request, it should return the addresses of different record types.
app.post('/', (req, res) => {
// Request format
// const l = {
// lookup: 'twitter.com',
// recordTypes: ['A', 'TXT']
// };
// Using destructor to fetch properties
const { lookup, recordTypes } = req.body;
console.log(lookup, recordTypes);
// For each record type
recordTypes.forEach(function(type) {
// setTimeout to get something async
setTimeout(function() {
dns.resolve(lookup.toLowerCase(), type, (err, addresses) => {
console.log(type);
if (err) {
return console.log(`\nType(${type}):\n`, err);
}
result = result + JSON.stringify({ type: `${type}`, response: { addresses } });
console.log(result);
});
}, 2000);
});
res.send(result);
});
It logs the correct stuff in the console but when it comes to the response, it returns an empty string. I used setTimeout to mimic the asynchronous nature of the request but it just does not work.
Please assume that I have declared stuff like result etc. because it is working. Also, please don't to redirect me to the Node.js documentation because I have already read that stuff and that's not the problem here. The problem is that I need to get every record type in an array and send that back as a response.
Here's what I have tried:
Tried to push response for each record type in the result array,
Tried to use a for of loop instead of forEach
Please help!
The way I'm reading your code is that for each item in the array you correctly use callbacks to do each individual bit of processing.
However, remember that forEach itself is not asynchronous. Thus you are setting up a bunch of tasks that will complete sometime, then returning undefined... then your results start to trickle in.
There's a couple ways to correctly. As you are using callbacks here I will use that style. You want to get a callback when all items in an array have been completely processed. The async module does this very well, providing a lot of high quality methods that act on arrays and such and give you a way to have a callback when they are all over.
Your function will look something like:
let res = []
async.each( recordTypes,
( type, done ) => {
dns.resolve(lookup.toLowerCase(), type, (err, addresses) => {
result = result + JSON.stringify({ type: `${type}`, response: { addresses } });
done(err)
} )
},
(allOverError) => {
res.send(result);
}
)
Notice there are two function parameters here: the first one is called for every item in the list, and the last is called when every item in the list has been completely processed.
There are other ways too, promises or the async/await keywords (confusing because of the name of the async module), but callbacks are good.

Mapping the JSON values to the UI fields in Angular 4

I am trying to do an update operation using Mean Stack with Angular 4. I am new to this technology. For update oprtn I need to map the values to UI form based on id selected to update the record. My data service is fetching record values from MongoDb database in the form of JSON which needs to be updated. However, I am unable to set those parameters to the fields present over the form in the typescript code.
I am using JSON.parse method for implementing it But getting below error.
Error: SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse ()
Typescript code
updateitem(itemid){
let updatedresult;
console.log("toupdateid", itemid);
this.dataService.getItemById(itemid)
.subscribe(
res=> {
this.res =JSON.parse(res);
this.newSession.trainingName =res["TrainingName"],
this.newSession.description = res["Description"];
console.log('newsession', this.newSession);
},
err=> this.apiError = err,
() => {
this.getFormdetails();
}
)
}
dataservice
getItemById(id):Observable<any>{
console.log('idvalue', id);
return this.http.get("http://localhost:3000/getitem"+"/"+ id)
.map(result =>{ this.result = result.json();
console.log('getitembyid' ,result.json())})
.catch((error:any) => Observable.throw('Server Error to get the item'));
}
}
.map(result =>{ this.result = result.json();
console.log('getitembyid' ,result.json())})
Change it to
.map(result => result.json())
And remove the JSON.parse in ts code as now it will return from the service as a JSON object itself
That error occurs when server sends a invalid json. You need to check response of the server.
there are different reasons for that but most likely:
you are sending your request to a wrong endpoint. So instead of json you get a document starting with u and it tries to parse it.
Another one is server sending you a wrong response which is not in JSON format. Try to see if response is turned into a json string on server side.
But since it starts with u its most likely trying to parse an undefined string. I sugest instead of subscribing function you should nest promises like following.
getItemById(id):Observable<any>{
console.log('idvalue', id);
return this.http.get("http://localhost:3000/getitem"+"/"+ id).then(result => {
return result.json();
}) //this will return promise
.catch((error:any) => Observable.throw('Server Error to get the item'));
}
}
and on your updateItem
updateitem(itemid){
let updatedresult;
console.log("toupdateid", itemid);
this.dataService.getItemById(itemid)
.then(
res=> {
this.res =JSON.parse(res);
this.newSession.trainingName =res["TrainingName"],
this.newSession.description = res["Description"];
console.log('newsession', this.newSession);
this.getFormdetails();
}).catch(err => {
this.apiError = err
})
)
}

Resources