Using Q promises in HTTP requests with NodeJs
I am trying to chaining promises functions that use HTTP requests in NodeJS with Kraken framework.
My code could work 90% of the time, but if the remote server asks for a time to respond, the code will return an error with undefined values. Therefore, I think Q is a good solution to prevent this.
Here's the situation:
We access the URL with the "code" parameter -> the route controller takes this parameter to use it in the HTTP POST request -> the response (token) is stored in a variable and used in another HTTP GET request -> the response (multiple JSON objects) is also stored in a variable → all variables are stored in MongoDB. If functions are not used in that order, of course it fails.
var Q = require('q');
module.exports = function (router) {
router.get('/', function (req, res) {
var codein = req.param('code');
if(codein){
console.log('Provided code: ' + codein+'\n');
getAccessToken(codein).then(function(token){
console.log('Provided AccessToken: ' + token + '\n');
getUsername(token).then(function(userdata){
console.log('Provided Username: ' + JSON.parse(userdata).username + '\n');
storeData(userdata).then(function(msg){
console.log(msg);
res.redirect('/dashboard/' + JSON.parse(userdata).username);
});
});
});
}
else{
console.log('Access Denied, redirecting...');
res.redirect('/');
}
});
};
This method works, but didn't actually solve the problem because sometimes the variables are undefined again. I think these are my request functions which are not well done ...
Here's an example of the first function with a POST request:
var getAccessToken = function(cod){
var def = Q.defer();
var data = querystring.stringify({
client_id:"1234567890",
client_secret:"******",
grant_type:"authorization_code",
redirect_uri:"http://localhost:8000/r/callback",
code:cod
});
var options = {
host: 'domain.server.com',
port: 443,
path: '/api/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(data)
}
};
var response = "";
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
response += chunk;
});
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
});
req.write(data);
req.end();
return def.promise;
};
In this case, the acto variable might be undefined ... Am I using Q incorrectly?
EDIT
To understand my problem, let me show you what I have in my output console (really rare, but it happens):
Provided code: 12345678910
Provided Username: user543210
Instead:
Provided code: 12345678910
Provided AccessToken: 9876543210
Provided Username: user
source to share
I think you need to consider 2 scenarios
- If the Twitch API takes time to respond.
- Twitch response could not be parsed
Code
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
Should be changed as:
try {
var json = JSON.parse(response);
var acto = json.access_token;
//check if acto is undefined
if (acto === undefined) {
def.reject('Some error message');
} else {
def.resolve(acto);
}
} catch (error) {
//since the JSON could not be parse
def.reject(error);
}
source to share