I have some problems with the callback when I'm using Request npm.
My project is an API for the users developed by Sailsjs, on the other hand I'm using reactjs for the front-end, and I'm using Request npm to communicate with the API.
I have some issues with the callback.
My code :
handleClick(event) {
var apiBaseUrl = "http://localhost:1337/user";
if (
this.state.first_name.length > 0 &&
this.state.last_name.length > 0 &&
this.state.email.length > 0 &&
this.state.password.length > 0
) {
request.post({url : apiBaseUrl + "/store", form :{
first_name: this.state.first_name,
last_name: this.state.last_name,
email: this.state.email,
password: this.state.password
}}, function(response) {
console.log(response);
if (response.data.code === 200) {
var loginscreen = [];
loginscreen.push(
<Login
parentContext={this}
appContext={this.props.appContext}
key = {rand}
/>
);
var loginmessage = "Not Registered yet.Go to registration";
this.props.parentContext.setState({
loginscreen: loginscreen,
loginmessage: loginmessage,
buttonLabel: "Register",
isLogin: true
});
} else {
console.log("some error ocurred", response.data.code);
}
});
} else {
alert("Input field value is missing");
}
}
The post request is doing well, when I'm checking the database I found the user saved and the response in networking onglet in chrome is good, but when I do console.log(response) it's always null. I don't know if my callback isn't right, or if it's something else.
form
http response
variables in response
Error
Back-end
// Store user
store: function(req, res) {
var params = _.extend(req.query || {}, req.params || {}, req.body || {});
console.log(params);
UserService.store(params, function(err, user) {
if (err) return res.json();
if (!user) return res.json();
return res.send({
"code": 200,
"success": "user registered sucessfully"
});
});
},
Can you help me to fix this problem?
Actually, the problem is on your callback, the callback takes two arguments , it should be like this :
function(error, response) {.....}
the error is the first argument and the response is the second, you are getting null because there is no error ! and the response was treated as the error object.
Related
I read some tutorials on MEAN Stack and I'm currently working on one which is almost complete, until I tried my update function. I keep on receiving a 400 message and when i look at the chrome dev tools and under the network tab I read the response which is "_id" is not allowed.
here is the update function
$scope.update = () => {
console.log($scope.contact._id);
$http.put('/api/contacts/updatecontact/' + $scope.contact._id, $scope.contact)
.then(function(data) {
alert('Data was updated Successfully');
refresh();
});
};
here is the api.
app.put('/api/contacts/updatecontact/:id', (req, res) => {
const id = req.params.id;
console.log(req.body.name);
// validation
const { error } = validateInput(req.body);
if (error){
return res.status(400).send(error.details[0].message);
}
const updatedContact = Contact.where({ _id: id });
updatedContact.update({
$set: { name: req.body.name, email: req.body.email
}
}, (err, contact) => {
if(err){
console.log('error occured');
}
res.json(contact);
console.log('contact successfully updated');
});
console.log(updatedContact);
});
hope i can get some help with this.
It seems the node.api is validating the json object that you are passing. Make sure the properties you sent form the client.
Make sure you are not validating or remove the validation on the node.
I'm building a restful api using node express mongoose/mongo etc.. I'm trying to output an array of users that are being followed by a particular user. Here is the schema.
var UserSchema = new mongoose.Schema({
username: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/^[a-zA-Z0-9]+$/, 'is invalid'], index: true},
email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+#\S+\.\S+/, 'is invalid'], index: true},
bio: String,
image: String,
following: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }]
}, {timestamps: true});
So every User has array of users in an array in the key 'following'. I'm trying to output that list by first finding the user record through it's own id and then mapping through this array to find the followed users for this current user.
router.get('/users/friends', auth.required, function(req, res, next) {
var limit = 20;
var offset = 0;
if(typeof req.query.limit !== 'undefined'){
limit = req.query.limit;
}
if(typeof req.query.offset !== 'undefined'){
offset = req.query.offset;
}
User.findById(req.payload.id)
.then(function(user){
if (!user) { return res.sendStatus(401); }
return res.json({
users: user.following.map(function(username){
User.findById(username)
.then(function(userlist){
console.log('userlist:',userlist.username);
return userlist.username;
})
.catch(next)
})
})
})
.catch(next);
});
Now the console.log in this code outputs the correct data in the js console but I can't seem to find a way to deliver this to the client. So far my efforts bring forth 'null' values in the client. The correct amount of records but just null values. Any ideas how to fix this?
revised my code to this after taking advice below. Now it manages to get the first record to the client but then errors out with
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent.
Blockquote
router.get('/users/friends', auth.required, function(req, res, next) {
var limit = 20;
var offset = 0;
if (typeof req.query.limit !== 'undefined') {
limit = req.query.limit;
}
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
User.findById(req.payload.id)
.then(function(user) {
if (!user) {
return res.sendStatus(401);
}
Promise.all(
user.following
).then(function(userarray) {
console.log(userarray);
userarray.forEach(function(userid) {
Promise.all([
User.find({
_id: {
$in: userid
}
})
.limit(Number(limit))
.skip(Number(offset))
.populate('author')
.exec()
]).then(function(results) {
userdetails = results[0];
var userdetailsCount = results[1];
return res.json({
userdetails: userdetails.map(function(userdetail){
return userdetail;
})
});
})
})
})
})
.catch(next);
});
Your problem section is:
return res.json({
users: user.following.map(function(username){
User.findById(username)
.then(function(userlist){
console.log('userlist:',userlist.username);
return userlist.username;
})
.catch(next)
})
})
The bit User.findById(username) will return a promise. But you are not awaiting on that promise. I'm guessing you think that the then function following that promise, which logs userlist.username to the console and returns it, should mean that your map function returns a list of userlist.username's. But this is not the case. Your map function is returning an array of promises.
What you really want is a feature like Bluebird's Promise.map: http://bluebirdjs.com/docs/api/promise.map.html (or, look for a similar feature, to deal with arrays of promises, in whichever promise library you happen to be using).
Trying to authenticate with passport via AngularJS. I've found a lot of threads saying that the issue is the default Content-Type of the request. Tried a couple of ways and I always get a 400 Error (Bad Request).
$http.post('/login', {
username: $scope.user.username,
password: $scope.user.password
})
.success(function(user) {
console.log('success');
// $location.url('/');
})
.error(function() {
console.log('failed');
// location.url('/login')
})
[Snipped some stuff that I don't think is the issue]
UDPATE: I think this might be an issue with passport. Using the body-parser middleware, I'm able to tell that I'm sending the data in the following format:
{ username: me, password: 12345 }
Alas, I still get the error code 400.
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
app.post('/login', jsonParser, function(req,res) {
if (!req.body) {
console.log('no body');
return res.sendStatus(400);
}
console.log(req.body);
res.end(req.user);
});
Here's the local strategy
passport.use(new LocalStrategy(
function(username, password, done) {
if (username === "me" && password === "123") {
return done(null, {name: "me"});
}
return done(null, false, {message: 'Incorrect username or password.'});
}
));
And the route for when I try to get passport to work.
app.post('/login',passport.authenticate('local'), function(req,res) {
console.log('login in server.js')
res.send(req.user);
});
Pretty sure this is all standard, based on everything I've read.
Needed this...
var bodyParser = require('body-parser');
app.use(bodyParser.json());
I am using "$http.get" for send request. My API response in browser, it returns what i want. But in Ionic App, it return HTML body tag text.
My Code is:
var params = {
email: 'test#gmail.com',
password: '123'
}
$http.get("https://www.nepalivivah.com/API/index.php/accessapi/loginapi", { params: params }).then(function (data) {
alert(JSON.stringify(data));
}).error(function (data) {
alert(JSON.stringify(data));
});
This is my AngularCode. When i run it in postman, it return valid response. But in Ionic App not Working.
If you want the $http.get, this should work.
var params = {
email: 'test#gmail.com',
password: '123'
}
$http.get("https://www.nepalivivah.com/API/index.php/accessapi/loginapi").then(function (data) {
alert(JSON.stringify(data));
}).error(function (err) {
alert(JSON.stringify(err));
});
However, in this case, what you are trying to do is to login into something. A get request will not work with this. You need to use $http.post at least in this case.
I've read several of the other posts about this problem and none of the solutions seem to be working for me. I have the following code in my View:
this.model.set({
username: $('#user-username').val(),
role: $('#user-role').val(),
description: $('#user-description').val()
});
this.model.save({ user_id: this.model.get('user_id')}, {
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
and this on my server controller (nodejs running express 3):
UserController.prototype.updateAction = function(req, res) {
if (req.route.method != "put") {
res.send({status: "error", error: "update must be put action and must include values"});
return false;
}
var query = {'user_id': req.params.id};
var user = req.body;
var userRepository = this.userRepository
// delete _id to avoid errors
delete user._id;
userRepository.update(query, user, {}, function(err, updated) {
if ((err) || (!updated)) {
res.send({"status": "error", "error": err});
return false;
}
// send updated user back
util.log('updated user ' + user.user_id);
res.setHeader('Content-Type', 'application/json');
res.status(200);
res.send(JSON.stringify({"status": "success", "updated": updated}));
});
}
On save, my model is saved correctly in the server and I have verified the server response with this. So, as far as I can tell the server is returning status 200, valid JSON, with a valid JSON response header. And yet my backbone model.save function always triggers the error callback. Can anyone please tell me why and how to resolve this?
I am able to get this to work if set the dataType to text like so:
this.model.save({ user_id: this.model.get('user_id')}, {
dataType: "text",
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
but doing so does not allow me to get the response back from the server. Instead I get this in the response var:
success: {
"_id": "5133b02062e15ed1d2000001",
}
Backbone expects to get back the model that it sent in its PUT or POST request body.
Instead of:
res.send(JSON.stringify({"status": "success", "updated": updated}));
Try this in your server's response:
res.json(user);
There may be a possibility that your call may have got in state 200 connection established which backbone detects as error, Backbone throws success only when the call is 200OK.
What's your server code? You need to make sure you're sending json back to backbone like so:
//In your express POST route
user.save(function(err) {
if(err){
console.log(err);
return res.json(401);
} else {
console.log('user: ' +user.username + ' saved');
return res.json(200);
}
Then in your backbone view you can check for the response and do what you need:
//some function in your view
this.model.save(this.formValues, {
success: function(model, response, options) {
if (response == 200) {
console.log('success :' + response);
//Do stuff
} else {
console.log('error: '+response);
//etc.
Also note that as per the backbone model documentation:
"save accepts success and error callbacks in the options hash, which will be passed the arguments (model, response, options)"