Reputation: 5486
I am writing my first node.js package to help make a REST API easier to use and I am having trouble formatting the package to allow the person using the package to do the below in their applications.
var Water= require("water-reservation");
var water = Water({username: myusername, password: mypassword});
// Problem here because Water({}) needs to do a REST call to get a bearer
// token to use the API I am trying to simplify. Thus, it tries to
// get_water(callabck) before the bearer_token var is set in my package.
water.get_water(function(err, result){
if(err){
console.log(err);
console.log("----------------------------------------------");
}
else{
console.log(result);
console.log("----------------------------------------------");
}
});
In my current setup I take the user's username and password and pass it to a REST endpoint to get a bearer token that I use in all my REST calls for the package. The async nature will call get_water in the users file before I am done with setting the bearer_token variable in my package.
Here is what my package looks like:
var request = require('request');
var bearer_token = "";
var api_url = "";
var Water = function(credentials){
api_url = credentials.api_url;
var username = credentials.username;
var password = credentials.password;
get_bearer_token(username, password, function(err, access_token){
bearer_token = access_token;
});
};
function get_bearer_token(username, password, callback){
var request_options = {
url: api_url + "/auth",
method: "GET",
'auth': {
'user': username,
'pass': password
}
};
request(request_options, function(err, res, body){
if(err) {
return callback("Water Initialization Error: " + err, null);
}
else {
return callback(null, body);
}
});
}
// Get water
Water.prototype.get_water = function(callback) {
var request_options = {
url: api_url + "/water",
method: "GET",
'auth': {
'bearer': bearer_token
}
};
request(request_options, function(err, res, body){
if(err) {
return callback(err, null);
}
else{
return callback(null, body);
}
});
};
// more package functions...
module.exports = Water;
I am trying to find a way to make the setup so the user can use the package as described above. I am not set on that style, but it seems to be the easiest for a user to understand and use.
The only way I could think of fixing this is add a callback to Water({}) but that would make a lot of mess having the user wrap all their water related code in the callback. I know it can be done by looking at the Twitter package for example, but I still could wrap my mind around how they did it. Any help would be appreciated, thanks.
Upvotes: 2
Views: 160
Reputation: 2646
You should delegate the responsibility of getting the token to when they make a request. That way the package is initialised instantly. To make it more efficient you can cache the token the first time it is fetched. I've made an example here, but you could tidy it up using something like async:
var request = require('request');
var Water = function (credentials) {
this.api_url = credentials.api_url;
this.username = credentials.username;
this.password = credentials.password;
return this;
};
Water.prototype.get_bearer_token = function (callback) {
// We already have the bearer token, so return straight away
if (this.bearer_token) return callback(null, this.bearer_token);
var self = this;
var request_options = {
url: this.api_url + "/auth",
method: "GET",
'auth': {
'user': this.username,
'pass': this.password
}
};
request(request_options, function(err, res, body){
if(err) {
return callback("Water Initialization Error: " + err, null);
}
else {
self.bearer_token = body;
return callback(null, body);
}
});
}
// Get water
Water.prototype.get_water = function(callback) {
var self = this;
this.get_bearer_token(function (err, token) {
if (err) return callback(err);
var request_options = {
url: self.api_url + "/water",
method: "GET",
'auth': {
'bearer': token
}
};
request(request_options, function(err, res, body){
if(err) {
return callback(err, null);
}
else{
return callback(null, body);
}
});
});
};
// more package functions..
module.exports = Water;
To use it:
var Water = require('water-reservation');
var water = new Water({
username: 'username',
password: 'pass',
api_url: 'http://example.com'
});
water.get_water(function (err, res) {
});
Upvotes: 1