request-promise in node not working as expected - javascript

I am using request-promise node module. I have been following the docs, and believe I should have set everything up correctly, however, I am getting the following error:
Unhandled rejection StatusCodeError: 400 - "{\n \"error\" : {\n
\"status\" : 400,\n \"message\" : \"invalid id\"\n }\n}"
at new StatusCodeError (/Users/fitz035/Desktop/sony/travelLand/node_modules/request-promise/node_modules/request-promise-core/lib/errors.js:32:15)
My code looks like the following.
var request = require('request');
var rp = require('request-promise');
rp('apiOne' + mood)
.then(function(error, response, body) {
console.log(body)
}
}).then(function(error) {
for (var i = 0; i < array; i++) {
rp('apiTwo', function(error, response, body) {
console.log(body))
});
}
}).then(function(error, response, body) {
rp('apiThree' + songListUrl, function(error, response, body) {
console.log(body))
});
})
.catch(function(err) {
console.log(err)
});
EDIT
Is this the correct approach?
var options = {
uri: 'https://jsonplaceholder.typicode.com/posts/1',
json: true
}
rp(options).then(function(data){
console.log(data)
var optionsTwo = {
uri: 'http://www.google.com',
}
rp(optionsTwo).then(function(data){
console.log(data)
console.log(answer);
})
})

You're calling rp as though it were request in a couple of places, such as in your for loop. Since you're not doing anything with the return value of those calls, you're not handling either resolution or rejection of those promises, thus getting the error warning you that there was a rejection you didn't handle.
The calls that you do use the return value from look incorrect as well. The callbacks you're passing in declare NodeJS-callback style argument lists, but that's not how promises work. Instead of a single callback that gets passed an error or null as the first argument, you register separate callbacks for resolution (success) and rejection (error).
I suggest studying the examples on the request-promise page in detail.
Re your follow-up:
Is this the correct approach?
var options = {
uri: 'https://jsonplaceholder.typicode.com/posts/1',
json: true
}
rp(options).then(function(data){
console.log(data)
var optionsTwo = {
uri: 'http://www.google.com',
}
rp(optionsTwo).then(function(data){
console.log(data)
console.log(answer);
})
})
No, that still doesn't handle rejections. If your goal is to do those two requests in series (not in parallel), then see comments:
var options = {
uri: 'https://jsonplaceholder.typicode.com/posts/1',
json: true
};
rp(options)
.then(function(data){
console.log(data)
var optionsTwo = {
uri: 'http://www.google.com'
};
return rp(optionsTwo).then(function(data){ // Note the return
console.log(data)
console.log(answer); // Don't know where `answer` is coming from...?
// Note that by not returning anything, you convert
// the resolution value to `undefined`. That's fine if
// you don't need it, but it's worth pointing out.
});
})
.catch(function(error) {
// One of the two operations above failed
});

Related

How to use a conditional validation after Axios call in Vue app

I have a Vue application where I make a POST request to my backend. I am now trying to call a validation method after the response from my backend returned back an error to my frontend. But for some reason my code is not executed:
UPDATED QUESTION CODE:
validateFormInput(){
this.$refs.form.validate()
},
saveSelectionVoter() {
var pageURL = window.location.href;
var lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
this.votersSelectArray.voterAvailableTimes = [...this.votersSelectArray.voterAvailableTimes, ...this.selected]
console.log(JSON.stringify( this.votersSelectArray))
axios.post("http://localhost:8080/api/votercontroller/",
this.votersSelectArray,
{
params: {
meetingName: lastURLSegment,
}
},
).then(function(response){
})
.catch(function (error){
this.validateFormInput()
console.log(error)
})
this.selected = []
},
This causes a new error:
TypeError: Cannot read property 'validateFormInput' of undefined
always have a catch to see the error return
axios return you a promise so it captures the error if there is any
axios.post('url')
.then((res) => {
// do somthing
}).catch(err){
console.log(err)
}
You can either use the callback method to catch the response/error or use the Promise way, which is my favorite because of scope and readability.
You start by declaring your function with async
async saveSelectionVoter() {
Then you use a try/catch block to handle the response/error:
try{
const response = await axios.post(url, params)
// handle response here
} catch (error) {
// handle error here
}

Axios code not running after `.then`

I am new to react/nodejs/express/javascript and have encountered the following problem:
I want to get a number, then post that number + 1, then I want to create a new js object using that number(newFreshId) and I want to add it to add that event to my schedulerData. When I try running the code, I can get and post to /api/num, but I everything after the .then(function(response) { doesnt appear to run.
I wanted to do this sequentially, so I used .then after every task so that I would not have encountered a problem.
I also tried to remove all the .thens in favor of a while loop that waits for the value to change. This also did not work.
CODE:
CLIENT:
this.newEvent = (schedulerData, slotId, slotName, start, end, type, item) => {
let newFreshId = 0;
let newEvent = {}
axios.get("/api/num").then(function(response) {
newFreshId = response.data[0] + 1;
// console.log(newFreshId);
}).then(function() {
axios.post("/api/num", {
id: newFreshId
}).then(function(response) {
console.log(response)
// handle success
newEvent = {
id: newFreshId,
title: this.state.title,
start: start,
end: end,
resourceId: slotId
};
schedulerData.addEvent(newEvent);
this.setState({
viewModel: schedulerData
});
// while(JSON.stringify(newEvent) === '{}'){
// console.log('waiting')
// }
console.log(newEvent)
schedulerData.addEvent(newEvent);
console.log(newEvent)
this.setState({
viewModel: schedulerData
});
})
})
};
SERVER:
app.get('/api/num', function(req, res) {
//console.log(require('./number.json'))
var fs = require('fs')
fs.readFile('./number.json', {encoding: 'utf-8'}, function(err,data){
if (!err) {
//console.log('received data: ' + JSON.parse(data));
res.json(JSON.parse(data))
} else {
console.log(err);
}})
})
app.post('/api/num', function(req, res) {
var id = req.body.id
var fs = require('fs');
fs.writeFileSync("./number.json", "[ "+id+" ]", function(err) {
if(err) {
return console.log(err);
}
res.status(200)
})
})
Thanks for all the help :)
fs.writeFileSync doesn't have a callback, so the function you're adding never gets executed: https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options
This means the response is never sent back to the client, and the axios promise is never resolved.
Try using fs.writeFile with a callback: https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback
It's also a good idea to send a response in the case of an error, too.
app.post('/api/num', function(req, res) {
var id = req.body.id
var fs = require('fs');
fs.writeFile("./number.json", "[ "+id+" ]", function(err) {
if(err) {
console.log(err);
return res.status(200)
}
res.status(200)
})
})
Finally, though it wouldn't help you in this situation, you should add a .catch to the very tail end of your axios chain. Any errors that take place in the promise chain will wind up there.
An example:
axios.get(specs).then(someFunction).catch(e => console.error(e));
for me I was facing the same issue and I figured it out that because I'm using some redirection after making a post request
window.location.href = "/{redirect to some rout}"
this makes the console change immediately so I couldn't see the then response unless I removed the redirection.
I too faced an issue where I wasn't able to run the .then() or .catch() code
const fetch = async() => {
axios.get("https://jsonplaceholder.typicode.com/todos/1")
.then((res) => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
All I did was add async to the function and it started working
const axios = require('axios').default;
use it like this

meteor.call with callback returning undefined

I appreciate that there are many questions on this but I can't seem to find a relevant answer.
I am using a Meteor call with a callback to a method on the server that shrinks an URL via bitly, but although this runs on the server, I am getting a undefined response back on the client.
Any ideas here is the code?
Client
Meteor.call('bitlyShrink','http://test.com', function(error, response) {
console.log(error);
console.log(response);
})
Server
Meteor.methods({
bitlyShrink(longurl) {
check (longurl, String);
const BitlyClient = require('bitly'),
bitly = BitlyClient('token');
bitly.shorten( longurl )
.then( function ( response ) {
console.log(response);
return response;
})
.catch( (error ) => {
return error;
});
}
});
That's a common mistake made while using Promises in Meteor methods.
To make Meteor resolve a Promise and return result to a client you should return the Promise at the end of this method:
Meteor.methods({
bitlyShrink(longurl) {
check (longurl, String);
const BitlyClient = require('bitly'),
bitly = BitlyClient('token');
const bitlyPromise = bitly.shorten(longurl);
// do something else, if needed
return bitlyPromise;
}
});
You should not add .catch(), it will be added by Meteor automatically.
Useful article to read: Using Promises and async/await in Meteor.

Meteor: Exception in delivering result of invoking method

Similar issues have been posted, but none quite match what I've run into. I'm doing a simple POST to an internal server to get back product data. The call is successful and I see the JSON data correctly logging to my terminal when I do a console.log on the server side. The issue arises on the client side, when in the callback, the result and error both are undefined.
Server:
Meteor.methods({
ProductSearch: function(searchTerm) {
var method = 'POST';
var url = 'server';
var options = {
headers:{"content-type":"application/json"},
data: {
query:"trees"
}
};
return HTTP.call(method, url, options, function (error, result) {
if (error) {
console.log("ERROR: ", result.statusCode, result.content);
} else {
var txt = JSON.parse(result.content);
console.log("SUCCESS: Found "+txt.totalResults+" products");
}
});
}
});
Client:
Meteor.call('ProductSearch', searchTerm, function (error, result) {
if (error) {
console.log("error occured on receiving data on server. ", error );
} else {
var respJson = JSON.parse(result.content);
Session.set("productSearchResults", respJson);
}
});
When I log the values of error, and result on callback, they are both undefined, and I get the following error: Exception in delivering result of invoking 'ProductSearch': TypeError: Cannot read property 'content' of undefined
In your server-side method, you're not correctly returning the result of the HTTP.call, since you're using the asynchronous version, HTTP.call will return undefined and the result will only be accessible in the callback.
Use the synchronous version of HTTP.call instead and you'll be fine.
try{
var result = HTTP.call(method, url, options);
return JSON.parse(result.content);
}
catch(exception){
console.log(exception);
}
See the corresponding docs for HTTP.call for additional information.
asyncCallback Function
Optional callback. If passed, the method runs
asynchronously, instead of synchronously, and calls asyncCallback. On
the client, this callback is required.
https://docs.meteor.com/#/full/http_call

Return Meteor.http results in method

I have a Meteor method that wraps around an http.get. I am trying to return the results from that http.get into the method's return so that I can use the results when I call the method.
I can't make it work though.
Here's my code:
(In shared folder)
Meteor.methods({
getWeather: function(zip) {
console.log('getting weather');
var credentials = {
client_id: "string",
client_secret: "otherstring"
}
var zipcode = zip;
var weatherUrl = "http://api.aerisapi.com/places/postalcodes/" + zipcode + "?client_id=" + credentials.client_id + "&client_secret=" + credentials.client_secret;
weather = Meteor.http.get(weatherUrl, function (error, result) {
if(error) {
console.log('http get FAILED!');
}
else {
console.log('http get SUCCES');
if (result.statusCode === 200) {
console.log('Status code = 200!');
console.log(result.content);
return result.content;
}
}
});
return weather;
}
});
For some reason, this does not return the results even though they exist and the http call works: console.log(result.content); does indeed log the results.
(Client folder)
Meteor.call('getWeather', somezipcode, function(error, results) {
if (error)
return alert(error.reason);
Session.set('weatherResults', results);
});
Of course here, the session variable ends up being empty.
(Note that this part of the code seems to be fine as it returned appropriately if I hard coded the return with some dummy string in the method.)
Help?
In your example Meteor.http.get is executed asynchronously.
See docs:
HTTP.call(method, url [, options] [, asyncCallback])
On the server, this function can be run either synchronously or
asynchronously. If the callback is omitted, it runs synchronously and
the results are returned once the request completes successfully. If
the request was not successful, an error is thrown
Switch to synchronous mode by removing asyncCallback:
try {
var result = HTTP.get( weatherUrl );
var weather = result.content;
} catch(e) {
console.log( "Cannot get weather data...", e );
}
Kuba Wyrobek is correct, but you can also still call HTTP.get asynchronously and use a future to stop the method returning until the get has responded:
var Future = Npm.require('fibers/future');
Meteor.methods({
getWeather: function(zip) {
console.log('getting weather');
var weather = new Future();
var credentials = {
client_id: "string",
client_secret: "otherstring"
}
var zipcode = zip;
var weatherUrl = "http://api.aerisapi.com/places/postalcodes/" + zipcode + "?client_id=" + credentials.client_id + "&client_secret=" + credentials.client_secret;
HTTP.get(weatherUrl, function (error, result) {
if(error) {
console.log('http get FAILED!');
weather.throw(error);
}
else {
console.log('http get SUCCES');
if (result.statusCode === 200) {
console.log('Status code = 200!');
console.log(result.content);
weather.return(result);
}
}
});
weather.wait();
}
});
There's not really much advantage to this method over a synchronous get in this case, but if you're ever doing something on the server which can benefit from something like an HTTP call running asynchronously (and thus not blocking the rest of the code in your method), but you still needs to wait for that call to return before the method can, then this is the right solution. One example would be where you need to execute multiple non-contingent gets, which would all have to wait for each other to return one by one if executed synchronously.
More here.
Sometimes asynchronous calls are preferable. You can use async/await syntax for that, and you need to promisify HTTP.get.
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
const httpGetAsync = (url, options) =>
new Promise((resolve, reject) => {
HTTP.get(url, options, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
Meteor.methods({
async 'test'({ url, options }) {
try {
const response = await httpGetAsync(url, options);
return response;
} catch (ex) {
throw new Meteor.Error('some-error', 'An error has happened');
}
},
});
Notice that meteor test method is marked as async. This allows using await operator inside it with method calls which return Promise. Code lines following await operators won't be executed until returned promise is resolved. In case the promise is rejected catch block will be executed.

Categories

Resources