Im trying to call my nodejs server and show the results from an angularjs app. ive been following an example, but when i change the example code for my code, it always calls the error callback. i have a feeling its something wrong with my server, but i cant make it work, its nodejs without express or other libraries, and all other answers involve using express. how can i make it work without using express?
the code in angularjs, where i call the server:
app.controller('Main', function ($scope, $http) {
$scope.init = function() {
//var api = 'http://api.trakt.tv/calendar/premieres.json/7c989229f2fa626832e7576eb59820e9/20131103/30/?callback=JSON_CALLBACK';
$http.jsonp('http://localhost:8888/selectAllLocations?callback=JSON_CALLBACK').success(function(data) {
console.log(data);
}).error(function(error) {
console.log('My error: ' + error);
});
};
});
if i use the value in the var api, the result is ok and success is called, not with mine.
This is the code in my nodejs server.
var result = sequelize.query(query, null, options, parameters)
.success(function (rows) {
if (type == 'select') {
response.writeHead(200, { "Content-Type": "application/json" });
response.write(JSON.stringify(rows));
response.end();
} else if (type == 'modify') {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Query was successful");
response.end();
}
}
).error(function (e) {
console.log("An error occured: ", e);
response.writeHead(404, { "Content-Type": "text/html" });
response.write("There was an error man, shits on fire yo ---> " + e);
response.end();
}
);
Im pretty sure i have to wrap the json result in a function, but i dont know how, and i cant even know the function name, as this is all i get in my server:
path: /selectAllLocations
params: {"callback":"angular.callbacks._0"}
I understand im returning the pure json, and i can see it in chrome in my response, so, there is something preventing it from calling the success function. Can somebody point me in the right direction?
The function name is specified as the callback parameter.
response.write(params.callback + '(' + JSON.stringify(rows) + ')');
Related
So I'm having trouble getting one javascript function to finish before the next one starting. I've spent quite a lot of time trying to use callback methods described on other stackoverflow posts. I could get simple examples that used timeouts to work but couldn't get it to work with my API request. I stumbled upon async.js and thought that perhaps using async.series would be a good idea to get my two functions to perform one after another. So I tried this approach, however I still seem to be having the problem where the first function takes a bit longer to execute (which is fine) but the execution process moves past this function instead of waiting for it to end. I feel I have a misconception of some sort since I have tried several methods but to no avail.
What is strange is, is that that when running server.js, it goes into the first function but then it leaves the async.series() function even before the request is finished. When I print inside of tokenReq(), I can see that the request was successful as a token code is returned successfully however this happens to late as execution has moved on. The output is shown below.
server.js:
var access_code;
async.series([
function() {
access_code = queries.data.tokenReq(code);
console.log("Finished inside function 1");
},
function() {
console.log("\n Starting function 2 \n");
if (access_code === "error") {
res.json("An error has occured");
} else {
var response = queries.data.messagesReq(access_code);
res.json(response);
}
}
],
function(err, access_code) {
});
console.log("Outside");
queries.js:
tokenReq: function(code) {
var tokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
var form = {
code: code,
client_id: "__ID__",
redirect_uri: "__Site__/",
grant_type: "authorization_code",
client_secret: "__Secret__",
};
var formData = querystring.stringify(form);
var contentLength = formData.length;
request({
headers: {
'Content-Length': contentLength,
'Content-Type': 'application/x-www-form-urlencoded'
},
uri: tokenUrl,
body: formData,
method: 'POST'
}, function (error, response, body) {
if (error != "null") {
var access_token = JSON.parse(body).access_token;
console.log("\n INSIDE FUNCTION REQUEST, Token: " + access_token + " \n");
return access_token;
} else {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
// console.log('body:', body); // Print the HTML for the Google homepage.
return "error";
}
});
},
Output:
Finished inside function 1
Outside
INSIDE FUNCTION REQUEST, Token: 8Swhd.......
You missed a major point here. Since node.js is asynchronous there should not be a way to know when a function completes its execution. That is why we specify callbacks so that the invoking function knows whom to call when it finishes its execution. Once you have functions with callbacks, you can enforce series/parallel/waterfall behavior with async module.
tokenReq: function(code, cb) {
var tokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
var form = {
code: code,
client_id: "__ID__",
redirect_uri: "__Site__/",
grant_type: "authorization_code",
client_secret: "__Secret__",
};
var formData = querystring.stringify(form);
var contentLength = formData.length;
request({
headers: {
'Content-Length': contentLength,
'Content-Type': 'application/x-www-form-urlencoded'
},
uri: tokenUrl,
body: formData,
method: 'POST'
}, function (error, response, body) {
if (error != "null") {
var access_token = JSON.parse(body).access_token;
console.log("\n INSIDE FUNCTION REQUEST, Token: " + access_token + " \n");
return cb(null, access_token);
} else {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
// console.log('body:', body); // Print the HTML for the Google homepage.
return cb(new Error("whatever"));
}
});
},
Now, you can use the callback inside server.js
var access_code;
async.series([
function(cb) {
return queries.data.tokenReq(code, cb);
},
function(access_code, cb) {
console.log("\n Starting function 2 \n");
if (access_code === "error") {
res.json("An error has occured");
} else {
var response = queries.data.messagesReq(access_code);
res.json(response);
}
// do whatever you want after this
return cb();
}
],
function(err, access_code) {
if (err) {
console.log(err);
}
// wrap your logic around a function and call the correspoding callback here
});
I'm attempting to make a Web 2.0 API call via AngularJS using $http.post that returns JSON and as weird as this may sound, it worked an hour ago, now it doesn't and I haven't changed a thing. The application continues to work in all other browsers, it just fails in Edge.
var _login = function (loginData) {
var data = "";
var grant = [insert data to authorise user on server];
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
_userlogin(response);
deferred.resolve(response);
}).error(function (err, status) {
console.log(err + " " + status);
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
I've had to take some info out there because it's security info, but the functionality should be the same, so, from debugging I know that this is where the application stumbles. I also know that the logindata passed in is valid and I've tried the same call with the same grant on a REST client and that works fine also like I mentioned before the same call with no alterations runs in any other major browser (including IE weirdly).
When that call is run, the front end angular does the following:
$scope.authUser = function (username, password) {
var loginData = { userName: username, password: password, useRefreshTokens: login.useRefreshTokens}
authService.login(loginData).then(function (response) {
console.log(response);
sessionStorage.setItem("status", "User Logged In As: ");
sessionStorage.setItem("username", username);
global.template = "templates/dashboard.html";
login.password = "";
},
function (err) {
console.log(err);
login.message = err.error_description;
$("#passwordError").modal();
});
};
The application stops at login.message = err.error_description;, because it's not returned from the API call. The error is: Network Error 0x2efd, Could not complete the operation due to error 00002efd. and Unable to get property 'error_description' of undefined or null reference.
Edit: Forgot to mention - the application works when Fiddler is open and capturing traffic. That's the strangest part.
Take a look at this post which used the solution mentioned here. They're saying the issue was with interacting between localhost to localhost.
I'm glad I was able to help.
I'm a bit new to all this (including Javascript callbacks and ES6). I'm using NodeJS + Express + MongoDB.
I'm calling an Ajax function to update an item and the success Ajax call is never done.
Here is my Ajax call (called from React)
editBug : function(bug){
console.log('about to edit bug with these values',bug);
$.ajax({
url:'/api/bugs',
method: 'PUT',
data:bug
})
.done((jqxhr) => {
console.log('succcess while editing the bug');
this.setState({successVisible : true});
})
.fail((jqxhr) => {
console.log('error : ' + jqxhr);
})
},
Here is my API function:
app.put('/api/bugs',function(req,res){
//console.log('req',req);
console.log('query string : ',req.query);
console.log('query params : ',req.params);
console.log('query body: ',req.body);
let id = new ObjectID(req.body._id);
req.body._id = new ObjectID(req.body._id);
db.collection('bugs').replaceOne(
{_id:id},
req.body,
function(err,result){
assert.equal(err,null);
console.log('Successfull replace!');
res.status(200);
}
);
});
The Successfull replace! log is correctly shown on the server side.
The about to edit bug with these values is correctly shown on the front side. But the succcess while editing the bug log is not shown on front end and it seems .done call is never executed.
The problem is that you are not sending any response back to the browser on node side. Try the following snippet and you should be good to go
Also, I'd like to point out that you should handle the errors. While updating the bugs if something goes wrong, the best practice would be to inform the browser with the 500 status code indicating that the intended action failed. I've added this aspect in the snipped below
app.put('/api/bugs', function(req, res) {
//console.log('req',req);
console.log('query string : ', req.query);
console.log('query params : ', req.params);
console.log('query body: ', req.body);
let id = new ObjectID(req.body._id);
req.body._id = new ObjectID(req.body._id);
db.collection('bugs').replaceOne({
_id: id
},
req.body,
function(err, result) {
if (err) {
console.log('Failed replace');
res.status(500).end(); // <- We set the response status code and end the request
} else {
assert.equal(err, null);
console.log('Successfull replace!');
res.status(200).end(); // <- We set the response status code and end the request
}
}
);
});
Don't you need to end your response object on the Node.js side?
Try adding res.end(); or any kind of response to your response object.
Also, you can use chrome's (or any other browser's) network tab to actually see how your AJAX requests end up, to see if they hang or finish.
I have the following code
this.userInfo = 'bla';
request({
url: 'https://api.api.ai/v1/entities?v=20150910',
headers : {
Authorization: "Bearer " + process.env.APIAI_ACCESS_TOKEN
},
method: 'GET'
}, function (error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
console.log(this.userInfo);
}.bind(this));
When I try to print the this.userInfo variable I get undefined but I did the bind() on this. Could someone explain me what's going on ?
In your code scope of this is override by other functions so the value which you have set is not available.
When you call bind with this which is available out side function then it have same value as you have set, see below corrected code.
let self= this;
self.userInfo = 'bla';
request({
url: 'https://api.api.ai/v1/entities?v=20150910',
headers : {
Authorization: "Bearer " + process.env.APIAI_ACCESS_TOKEN
},
method: 'GET'
}, function (error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
//scope of 'this' in callback function are removed, so have set value to self variable
console.log(self.userInfo);
}.bind(this));
I'd highly recommend checking out the MDN article on the this keyword in JavaScript, to me it looks like you're misunderstanding the purpose of the this keyword in JavaScript.
In Node.js it's slightly different too, in the browser in the global scope, this is always window.
In Node.js all modules are executed in their own closure, whereas by default browsers run the global scope.
TL;DR as far as I know you can't write code like this in JS. Check out this StackOverflow answer for more detail.
Instead of using this you may want to setup a variable within that module, and store userInfo into that.
I am in the process of building my first Node app, and I am having troubles with unirest.get requests. My project is built using Node, Express, Node and the Act On API.
I am using the express generator to get the project of the ground quickly.
The problem I am experiencing is that I am struggling to get the response through to my route file. I am requesting a list from the Act On API which is returning correctly as I can see the response in the console when I log it, but cannot get the data through to the templates.
function getTheList(callback) {
var Request = unirest.get('https://restapi.actonsoftware.com/api/1/list/l-0001')
.headers({
'Accept': 'application/json',
'Authorization': 'Bearer ' + access_token
})
.query({
"count": 20,
"fields": "First Name;Last Name;Email;"
})
.end(function(response, error) {
var data = response.body.data;
if (!error && response.statusCode == 200) {
callback(returnData(data));
} else {
console.log('Failed response');
}
});
}
function returnData(theData){
console.log(theData);
return theData;
}
module.exports.get = getTheList;
And the code inside my routes file to get this information.
var masterList = require('../acton/getMasterList');
var myListVar = masterList.get();
Any help on what I am doing wrong would be greatly appreciated.
The getTheList function that you describe expects a callback which you don't provide when you call it like so masterList.get().
So you can either do something like:
masterList.get(function(data){
//you can access data here.
})
Or, in the getTheList implementation just do away with the callback entirely.
.end(function(response, error) {
var data = response.body.data;
if (!error && response.statusCode == 200) {
returnData(data); //Just do this may be.
} else {
console.log('Failed response');
}
});