Asynchronous Javascript Request Issue (Node, request-promise module) - javascript

I am building an application and having an issue with making a request from the client, sending it to my server, having the server make the API call and then send the result back to the client. I am using Node and the Request-Promise module.
Here is the client side code:
$(document).ready(function() {
var artistSearch = () => {
const q = $('.artistName').val();
$.ajax({
type: "POST",
url: "http://localhost:3000/request",
data: {artist: q},
})
.done(function(data) {
console.log('data: ', data)
})
};
$(".artistSearch").submit( () => {
artistSearch();
});
});
This successfully makes a request to the server:
app.post('/request', (req, res) => {
const artist = req.body.artist;
const searchURL = "https://api.spotify.com/v1/search? q="+artist+"&type=artist";
var targetObj;
var options = {
uri: searchURL
};
rp(options)
.then(function (data) {
console.log(data);
res.send(data);
})
.then(function() {
console.log('complete');
})
.catch(function (err) {
console.log('error')
});
});
Which ultimately successfully grabs the data from the API call, but never sends it back to the client! If I do res.send() outside of my .then promise, I can receive data on the client end.
Is there something I am missing? Thanks in advance!

Try this
var options = {
uri: searchURL,
simple: false,
};
rp(options)
.then(function (data) {
console.log(data);
res.status(200).send(data).end();
})
.then(function() {
console.log('complete');
})
.catch(function (err) {
console.log('error')
});

I think the client did receive data, but the connection didn't terminate correctly as it thinks there are more data. This is because you didn't specify the header and the module http couldn't figure out the content-length.
rp(options)
.then(function (data) {
console.log(data);
// res.send(data);
// assume data is JSON.
res.setHeader (200, {'Content-Type': 'application/json',
'Content-Length':data.byteLength});
res.end(data); //Send data immediately.
})
...
If data is a string, you will need to use data.length instead. In fact, if data is a string, then by default the header is {'Content-Type': 'application/json', 'Content-Length':data.length}

Related

How to get response from a dynamic amount of URL's and combine JSON response from all of them

Currently I have a small JSON file with a list of URL's to fetch data from, this amount can change at any time, so I have built a small function to request from the URL's and log a JSON response from each of them, but currently I need to combine the responses from all of them and send them in a res.json format.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
var o1 = response.data
var obj = Object.assign(o1);
console.log(obj)
//res.json(obj.data);
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I was thinking that the code would look something like this (Pseudo code)
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
dynamic(var)object
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
add(response) to (var) object
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
when function is finished (console.log[(var)]) with added JSON from all of the requests
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I have seen solutions where the existing JSON data is overwritten if both the Response and JSON Object have the same value, and I want to avoid that.
I have tried storing the response data inside a var, but it would get overwritten if the data inside the var and the response had the same value.
I have also tried adding them together separately, but that makes numerous arrays, and I don't want that.
How you combine the json responses received completely depends on the information content of the response json. You can combine the responses as shown below or write custom logic to combine the jsons depending on actual responses and send the result.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
const JsonAggreagate = []
databases.find({}, async function(err, docs) {
try {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
let result = await axios.post(url, req.body)
//LOGIC FOR COMBINING JSON RESPONSES
JsonAggreagate.push({url: url, result : result})
}
} catch (error) {
console.log(error)
res.json({ success: false });
}
//when function is finished (console.log[(var)]) with added JSON from all of the requests
res.json({ success: true, result : JsonAggreagate});
});
} catch {
console.log(error)
res.json({ success: false });
}
});

Unable to display a response from Axios

I am new to using Axios and struggling to display anything from a response function. I'm mainly interested to see see at least the response status. The only output I can see is when there is a 4xx code returned, but nothing when the call is successful.
Below is my code, any help would be appreciated:
setServiceGroupPromise(){
//Read data from ./data/sourcingRules.txt
let filePath = './data/sourcingRules.txt';
var fileData = fs.readFileSync(filePath, 'utf8');
console.log(fileData);
let postURL = `${siteConfig}`;
const config = {
method: 'post',
url: postURL,
params: {
'apiKey': process.env.SHIPPING_SERVICE_API_KEY
},
headers: {
'content-type': 'application/xml',
},
data: fileData
};
console.log(`Post request going to: ${postURL}`);
axios(config)
.then(function (response) {
console.log(response.data);
console.log(response.status);
})
.catch(function (error) {
console.log('The following error occurred : ' + error.message);
});
}
If you are not seeing anything from the console.log(response.data), try logging something like console.log({response}), or console.log('show me something', response.data)

Send back data from node.js to client side javascript

what I´m trying to do is the following I already set a fetch connection from client side JS to the server Node.JS when a person click on a button in HTML which triggers that in the server side looks for an element in the MongoDB database in it find´s it, but my question is how do I send that found element back to the client side JS.
Javascript Code:
var button = document.getElementById("1");
button.addEventListener("click", idss);
function idss() {
var id = this.id;
var data = {
name : id
}
fetch("/clicked", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(function(response) {
if(response.ok) {
console.log('awesome');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
}
NODE JS:
app.post("/clicked", (req, res) => {
var pro = (req.body.name);
Number(pro);
Product.findOne({"id": pro}, function(err, foundLList) {
if(err) {
console.log(err);
} else {
console.log(foundLList); //THE ELEMENT IS FOUND
}
}
);
});
What I´m trying to do is to send the found element to Javascript so I can added to another variable.
You have to use res object to send data back to client. Your node code will be:
app.post("/clicked", (req, res) => {
var pro = (req.body.name);
Number(pro);
Product.findOne({
"id": pro
}, function(err, foundLList) {
if (err) {
console.log(err);
return res.status(500).json({
ok: false,
error: err
});
} else {
console.log(foundLList); //THE ELEMENT IS FOUND
return res.status(200).json({
ok: true,
data: foundLList
});
}
});
});
and on client side, you can read the data like this:
fetch("/clicked", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(function(response) {
if (response.ok) {
console.log('got data: ', response.data);
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
}

Server is restarted after an axios request with express

My problem is, My project's server is restarted After an axios request with express.
I can see http://localhost:3000/__webpack_hmr 200 OK in console of chrome.
when I add vocabulary to data or remove that, server is restarted.
This is the vue client code. (github link to file)
methods: {
addVocabulary () {
var vm = this
this.$validator.validateAll().then((result) => {
if (result) {
axios.post('/api/vc/add', {
vocabulary: this.vocabulary
}).then(function (response) {
vm.vocabularies = response.data
}).catch(function (error) {
console.log(error)
})
this.vocabulary = ''
} else {
console.log('Not valid')
}
})
},
remove (id) {
var vm = this
axios({
method: 'delete',
url: '/api/vc/remove',
data: {id: id},
headers: {'Content-Type': 'application/json'}
}).then(function (response) {
vm.vocabularies = response.data
}).catch(function (error) {
console.log(error)
})
}
}
And this is the server side code.link to file
router.post('/vc/add', function (req, res, next) {
if (!req.body) return res.sendStatus(400)
let vocabulary = req.body.vocabulary
let objVocabulary = {}
objVocabulary.id = 10
objVocabulary.content = vocabulary
vocabularies.push(objVocabulary)
fse.outputJson(file, vocabularies, err=>{
console.log(err);
fse.readJson(file, (err, data) =>{
res.json(data);
})
})
})
/* DELETE remove voca */
router.delete('/vc/remove', (req, res, next) =>{
if (!req.body) return res.sendStatus(400)
let id = req.body.id
var index = vocabularies.findIndex(voca => voca.id === id);
vocabularies.splice(index,1);
fse.outputJson(file, vocabularies, err=>{
console.log(err);
fse.readJson(file, (err, data) =>{
res.json(data);
})
})
})
Here's my project link to github,
I don't know why..
I see that you are using backpack.
Their documentation quotes: Live reload (on saves, add/delete file, etc.)
So, if you the JSON file you are manipulating in your server code is in a folder watched by backpack, hot module reload will kick in and restart the server.
Solution: Move the json to some other directory --> your database shouldn't be part of your source code anyways.

Why is request-promise not returning the results to postman and angular 2's map?

We have an Angular 4 service with a function like this:
callPostAPI() {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
let options = {}; //passing no options
return this.http.post('http://localhost:9000/v1/api/testapi', options, {
headers: headers
})
.map((response: Response) => {
return response.json();
})
.catch((error: Response) => {
return Observable.throw(error || 'server error');
});
}
The rp function is like this:
app.post("/v1/api/testapi", (req, res) => {
rp({
method: 'GET',
url: 'http://maps.googleapis.com/maps/api/geocode/json',
qs: {
address: '66309'
}
})
.then(res => {
console.log(res); //proper results received
return res;
}).catch(err => {
return err;
});
}
However, this is not returning any response when called either from postman or through Angular 4 service function.
The results are received and we can see them on the console as well. All this is working without headers.
Why is request-promise not returning the results?
You never handle the result of request promise on your server side. I'm assuming you are using express, try this:
app.post("/v1/api/testapi", (req, res, next) => {
rp({
method: 'GET',
url: 'http://maps.googleapis.com/maps/api/geocode/json',
qs: {
address: '66309'
}
})
.then(result => {
console.log(res); //proper results received
return res.status(200).json(result);
}).catch(next);
}
Use subscribe insted of then , i too had same issue but trying the above solved for me.

Categories

Resources