ERC20 token. Cannot get variable nor use methods with deployed contract - ethereum

I have deployed a ERC20 token contract via Metamask on the Ropsten network. The issue is that I am trying to interact with it via web3. I have followed the answers provided in SO and SE, related to token transfer and method calling.
As you will see, I am not transferring tokens here, but I am using my solidity contract method to set the initial owners of the token. The method in the contract receives 2 arguments, an address and also a tokenId.
When I use the code to transfer a token to the test Metamask account, it fails, in the sense that, if I enter into this test account and import the token, it has none.
For reference, This tokenId, is basically provided by my variable nextTokenIdToAssign, which I call this way:
const tokenIdToAssign = contract.nextTokenIdToAssign.call(function(err, res){
if(!err) { tokenIdToAssign = res; }
else { console.log("Error"); }
});
Oddly, when I try to console.log, it returns as undefined. Also, following the question comments, of this question I used
const test = web3.eth.getCode(contractAddress);
It just returns a null. The comments suggest that there is crash in my constructor, or a parent constructor.
Is there some important detail that I am missing here?
The complete code is the following:
const config = require('../config');
var Web3 = require('web3');
var web3 = new Web3();
const infuraApi = (config.infura.infuraApiKey);
//Set a provider (HttpProvider)
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'+infuraApi));
}
const EthereumTx = require('ethereumjs-tx');
var accountAddressHex = (config.metamaskAccount.metamaskAddressHex);
var accountAddressPrivateKey = (config.metamaskAccount.metamaskAddressPrivateKey);
var privateKey = new Buffer(accountAddressPrivateKey, 'hex');
var count = web3.eth.getTransactionCount(accountAddressHex);
var contractAddress = (config.solidityContract.contractAddress);
var contractAbiArray = (config.solidityContract.contractABI);
var contract = web3.eth.contract(contractAbiArray).at(contractAddress);
const testSendAccount= "0x...";
const gasPrice = web3.eth.gasPrice;
const gasPriceHex = web3.toHex(gasPrice);
const gasLimitHex = web3.toHex(30000000);
//const tokenTransferAmount = 1;
var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( {from: accountAddressHex}, function(err, hash){
if(!err) { tokenIdToAssignHex = hash;
console.log(tokenIdToAssignHex); }
else { console.log("Error"); }
});
var tokenIdToAssign = contract.nextTokenIdToAssign.call(function(err, res){
if(!err) { tokenIdToAssign = res; }
else { console.log("Error"); }
});
const test = web3.eth.getCode(contractAddress);
var rawTransaction = {
"from": accountAddressHex,
"nonce": web3.toHex(count),
"gasPrice": gasPriceHex,
"gasLimit": gasLimitHex,
"to": contractAddress,
"value": "0x0",
"data": contract.setInitialOwner.getData(testSendAccount, tokenIdToAssign, {from: accountAddressHex}), //contract.transfer.getData("0xCb...", 10, {from: "0x26..."}),
"chainId": 0x03 //Ropsten id is 3, replace with 1 for main
};
var tx = new EthereumTx(rawTransaction);
tx.sign(privateKey);
var serializedTx = tx.serialize();
web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
if (!err) { console.log( 'contract creation tx: ' + hash); }
else {
console.log(err);
return;
}
});
EDIT 1
Here is the contract code for the setInitialOwner:
function setInitialOwner(address _to, uint256 _tokenId) public
onlyOwner
tokensRemainingToAssign
tenKLimit (_tokenId)
yesZeroAddressOwner (_tokenId)
notSelfSend (_to, _tokenId) {
tokenIdToOwner[_tokenId] = _to;
balanceOfAddress[_to] = balanceOfAddress[_to].add(1);
emit Assign(_to, _tokenId);
tokenIndexArray.push(_tokenId);
uint256 length = balanceOf(msg.sender);
ownedTokensIndexMapping[_tokenId] = length;
addressToTokenIdByIndex[msg.sender][length] = _tokenId;
nextTokenIdToAssign = nextTokenFunc(nextTokenIdToAssign);
hypeKillsTokensRemainingToAssign = tokensRemainingToAssign.sub(1);
}
EDIT 2
I have changed the tokenToAssign and added the
var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( {from: accountAddressHex}, function(err, hash){
if(!err) { tokenIdToAssignHex = hash;
console.log(tokenIdToAssignHex); }
else { console.log("Error"); }
});

Since others may encounter this problem, I will post the solution I arrived at. The problem here was that my nextTokenToAssign variable was not updating properly.
I used myetherwallet.com to deploy the contract and to check its value. When I deployed the contract, if afterwards I did not call the constructor function, setting the initial value of nextTokenToAssign to 1, it would not update during the successive call to the setInitialOwner function. So the solution simply was to simply call the function.

Related

NodeJS to Postman Result

Good Day how can i compute a public function to route and check it on Postman? here is my codes
router.post('/post_regular_hours/:employee_id/',function(request,response,next){
var id = request.params.employee_id;
var time_in = request.params.time_in;
var time_out = request.params.time_out;
// const timein = request.params.time_in;
// const timeout = request.params.time_out;
knexDb.select('*')
.from('employee_attendance')
.where('employee_id',id)
.then(function(result){
res.send(compute_normal_hours(response,result,diff))
})
});
function compute_normal_hours(res,result,diff){
let time_in = moment(time_in);
let time_out = moment(time_out);
let diff = time_out.diff(time_in, 'hours');
return diff;
}
I want the Diff to get posted on Postman as a result
Here is the App.js of my codes. How can i call the data from mysql query to the function and return the computed data on router post
or can you guys give the right terminologies for it.
var express = require('express');
var mysql= require('mysql');
var employee = require('./routes/employee');
var time_record = require('./routes/time_record');
var admin_employee = require('./routes/admin_employee');
var tar = require('./routes/tar');
var Joi = require('joi');
var app = express();
app.get('/hello',function(req,res){
var name = "World";
var schema = {
name: Joi.string().alphanum().min(3).max(30).required()
};
var result = Joi.validate({ name : req.query.name }, schema);
if(result.error === null)
{
if(req.query.name && req.query.name != '')
{
name = req.query.name;
}
res.json({
"message" : "Hello "+name + "!"
});
}
else
{
res.json({
"message" : "Error"
});
}
});
//Database connection
app.use(function(req, res, next){
global.connection = mysql.createConnection({
host : 'locahost',
user : 'dbm_project',
password : 'dbm1234',
database : 'dbm_db'
});
connection.connect();
next();
});
app.use('/', employee);
app.use('/employee', time_record);
app.use('/admin', admin_employee);
app.use('/tar', tar);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(8000,function(){
console.log("App started on port 8000!");
});
module.exports = app;
Here is the App.js of my codes. How can i call the data from mysql query to the function and return the computed data on router po
There are a few problems with your code.
Please see explanations in the respective code chunks.
router.post('/post_regular_hours/:employee_id/',function(request,response,next){
// If you're receiving a post request
// you'll probably want to check the body for these parameters.
let id = request.params.employee_id; // make sure the param names are matching with what you post.
// This one is special because you are passing it through the url directly
let time_in = request.body.time_in;
let time_out = request.body.time_out;
knexDb.select('*')
.from('employee_attendance')
.where('employee_id',id)
.then(function(result){
// you are not sending time_in and time_out here - but difference. but difference is not calculated.
// changed the function signature a bit - you weren't using the result at all? leaving this callback here because I'm sure you want to map the used time to some user?
return response.send(compute_normal_hours(time_in, time_out))
});
});
// this function was (and still might be) incorrect.
// You were passing res and result which neither of them you were using.
// You also had time_in and time_out which were going to be undefined in the function scope. Now that we are passing them in it should be ok. Updated it so you don't have the params you don't need.
function compute_normal_hours(time_in, time_out){
// What was diff - if it's the time difference name things correctly
// You had a diff parameter passed in (which you didn't compute), a diff function called below and another variable declaration called diff.
// you were not passing time_in or time_out parameters.
// you have moment here - are you using a library?
let time_in = moment(time_in);
let time_out = moment(time_out);
let diff = time_out.diff(time_in, 'hours');
return `Computed result is: ${diff}`;
}
Important Edit
Please search for all occurences of res.render (response.render) and replace them with something like res.send - res.render is looking for the template engine

Aws JSON Lambda function, 'date-holiday' package

I am building an AWS Lambda function that emails the S3 location of call recordings to a mailbox if the office is out of hours. I can get it to send emails if any call is made but when I enter the conditions I fall down. I want the function to only operate on holidays and outside office hours(Christmas, bank holiday.....). I haven't tried weekends yet but I know how to go about doing that. I want to use the 'date-holidays' package but I am having trouble getting it to work. I can get the emails to send if it is not between 9 & 5 but I cannot get them to send if it is say Christmas day.
Or if there is an easier way, please suggest
var aws = require('aws-sdk');
var ses = new aws.SES({
region: 'us-west-2'
});
var time = new Date().getHours();
var td = new Date().getDate();
const s3 = new aws.S3({
apiVersion: '2006-03-01'
});
if (time > 17 || time < 9){
if (td == hd){
exports.handler = function(event, context, callback) {
console.log("Incoming: ", event);
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
const now = new Date();
const news = `Event took place in https://s3.console.aws.amazon.com/s3/object/${bucket}/${key}`;
const params = {
Bucket: bucket,
Key: key,
};
var eParams = {
Destination: {
ToAddresses: ["***********.com"]
},
Message: {
Body: {
Text: {
Data: `${news}`
}
},
Subject: {
Data: `Voicemail notification for ${now}`
}
},
Source: "*************.com"
};
console.log('===SENDING EMAIL===');
var email = ses.sendEmail(eParams, function(err, data) {
if (err) console.log(err);
else {
console.log("===EMAIL SENT===");
// console.log(data);
console.log("EMAIL CODE END");
console.log('EMAIL: ', email);
context.succeed(event);
}
});
}
}
};
I'm not sure what trouble you have it with 'date-holidays', you could try uploading node_modules folder also with Lambda and test (there is a data/holidays.json file)
var Holidays = require('date-holidays')
hd = new Holidays('US', 'la', 'no')
if(hd.isHoliday(--now--)) {
}

Jawbone API Paginated Results with 'page_token'

The Jawbone API returns paginated results of 10 json objects per result set. How does one obtain the rest of the paginated results?
The API documentation for the sleeps method indicates the existence of a page_token argument in the next object of the result set. My output below is missing this. Furthermore,the FAQ indicates this page_token takes an INT (presumably epoch) timestamp.
2nd: "page_token" parameter: if the request contains the "page_token" parameter, the API will return all the workouts, in
reverse order, (capped by "limit" or default of 10) that were
completed before that page_token. The page_token is a timestamp, and
there's a special case, when the request comes with page_token=0 which
is interpreted as passing page_token = CURRENT_TIMESTAMP, ie, give all
the workouts (with a limit)
I am able to authenticate with the API and return a set of 10 results (first paginated page)... but no page_token.
...snip json...
"links": {
"next": "/nudge/api/v.1.0/users/jMdCUPXZ-InYXo1kcdOkvA/sleeps?start_time=1424699101&updated_after=0&limit=10&end_time=1438723789"
},
"size": 10
Have I misunderstood the documentation? Could it be the documentation is out of date (wrong)? Or more likely, I'm completely misunderstanding this and writing horrible JS for my node.js ...
Can someone set me straight and show me how I can retrieve ALL results, not just the first page?
var express = require('express');
var app = express();
var port = process.env.PORT || 5000;
var passport = require('passport');
var config = require('./config.json');
var ejs = require('ejs');
var https = require('https');
var fs = require('fs');
var bodyParser = require('body-parser');
var jbStrategy = require('passport-oauth').OAuth2Strategy;
var jsonfile = require('jsonfile');
var util = require('util');
var path = require('path');
/* Calculate date range */
var $today = new Date()
var $start = new Date($today); $start.setDate($today.getDate() - 180);
var $end = new Date($today);
var $startDate = Math.floor(($start).getTime()/1000);
var $endDate = Math.floor(($end).getTime()/1000);
app.use(express.logger('dev')); // log every request to the console
app.use(bodyParser.json()); // read cookies (needed for auth)
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(passport.initialize());
/* Default Authentication Path */
app.get('/',
passport.authorize('jawbone', {
scope : config.jawboneAuth.scope,
failureRedirect: '/'
})
);
/* oauth callback from jawbone */
app.get('/done', passport.authorize('jawbone', {
scope : config.jawboneAuth.scope,
failureRedirect: '/'
}), function(req, res) {
var result = JSON.parse(body); console.log(result);
res.redirect('/sleeps');
}
);
app.get('/sleeps', function(req, res) {
var options = {
access_token : config.jawboneAuth.accessToken,
refresh_token : config.jawboneAuth.refreshToken,
client_id : config.jawboneAuth.clientID,
client_secret : config.jawboneAuth.clientSecret
};
if (!config.jawboneAuth.accessToken) {
// if there's no accessToken, go get one
res.redirect('/');
} else {
var up = require('jawbone-up')(options);
var page_token = [];
do {
up.sleeps.get({
page_token : page_token,
start_time : $startDate,
end_time : $endDate
}, function(err, body) {
if (err) {
console.log('Error receiving Jawbone UP data');
res.send(err);
} else {
try {
var result = JSON.parse(body);
var next_page_path = result.data.links.next;
//var next_page_token = next_page_path.split(path.sep);
//var page_token = next_page_token[5];
//page_token = result.data.links.next
console.log(result.data);
res.json(result);
} // end try
catch(err) {
console.log(err);
res.render('userdata', {
requestTime: 0,
jawboneData: 'Unknown result'
});
} // end catch(err)
} // end else
} //end callback fun
); // end up.sleeps.get()
} // end do
while(page_token[0] > 1);
} // end if
}); // end sleeps route
// Setup the passport jawbone authorization strategy
passport.use('jawbone', new jbStrategy({
clientID : config.jawboneAuth.clientID,
clientSecret : config.jawboneAuth.clientSecret,
authorizationURL: config.jawboneAuth.authorizationURL,
tokenURL : config.jawboneAuth.tokenURL,
callbackURL : config.jawboneAuth.callbackURL,
scope : config.jawboneAuth.scope,
passReqToCallback : true
}, function(req, accessToken, refreshToken, profile, done) {
// establish a pseudo user session.
var user = {};
// If there's no preexisting accessToken,
// write one to the config file.
if (!config.jawboneAuth.accessToken){
config.jawboneAuth.accessToken = accessToken;
config.jawboneAuth.refreshToken = refreshToken;
jsonfile.writeFile('./config.json', config, {spaces: 2}, function(err) {
console.error(err);
})
}
done(null, user);
}));
// HTTPS
var sslOptions = {
key : fs.readFileSync('./.server.key'),
cert : fs.readFileSync('./.server.crt')
};
var secureServer = https.createServer(sslOptions, app).listen(port, function(){
console.log('Listening on ' + port);
});
Turns out there is an undocumented limit parameter that has replaced the page_token.
The Jawbone Developer documentation is currently out of date. As is their FAQ (API section Question# 12).
A GET request like this seems to do the trick
https://jawbone.com/nudge/api/v.1.1/users/#me/sleeps?start_time=1388603458&end_time=1420139458&limit=1000

Angular JS correct factory structure

I have a factory in my AngularJS single page application that parses a given date against a JSON file to return season and week-number in season. I am currently calling the JSON file twice in each method $http.get('content/calendar.json').success(function(data) {....
How can i factor out the call to do it once regardless of how many methods?
emmanuel.factory('DayService', function($http, $q){
var obj = {};
obj.season = function(d){
// receives a mm/dd/yyyy string parses against Calendar service for liturgical season
d = new Date(d);
var day = d.getTime();
var promise = $q.defer();
var temp;
$http.get('content/calendar.json').success(function(data) {
for (var i=0; i<data.calendar.seasons.season.length; i++){
var start = new Date(data.calendar.seasons.season[i].start);
var end = new Date(data.calendar.seasons.season[i].end);
end.setHours(23,59);
//sets the time to be the last minute of the season
if (day >= start && day <= end){
//if given time fits within start and end dates in calendar then return season
temp = data.calendar.seasons.season[i].name;
//console.log(temp);
promise.resolve(temp);
break;
}
}
});
return promise.promise;
}
obj.weekInSeason = function(d){
//receives a date format mm/dd/yyyy
var promise = $q.defer();
$http.get('content/calendar.json').success(function(data) {
for (var i=0; i<data.calendar.seasons.season.length; i++){
d = new Date(d);
var day = d.getTime();
var end = new Date(data.calendar.seasons.season[i].end);
end.setHours(23,59);
end = end.getTime();
var diff = end - day;
if (parseFloat(diff) > 0){
var start = new Date(data.calendar.seasons.season[i].start);
start = start.getTime();
var startDiff = day - start;
var week = parseInt(startDiff /(1000*60*60*24*7))+1;
promise.resolve(week);
break;
}
}
});
return promise.promise;
}
obj.getData = function (d) {
console.log('DayService.getData')
console.log(today)
var data = $q.all([
this.season(d),
this.weekInSeason(d)
]);
return data;
};
return obj;
});
This solution assumes that content/calendar.json never changes.
I have answered a question which can help you in this problem one way or another. Basically you must fetch all necessary configurations/settings before the application bootstraps. Manually bootstrap the application, this means that you must remove the ng-app directive in your html.
Steps:
[1] Create bootstrapper.js as instructed in the answered question I have mentioned above. Basically, it should look like this(Note: You can add more configuration urls in urlMap, if you need to add more settings in your application before it bootstraps):
angular.injector(['ng']).invoke(function($http, $q) {
var urlMap = {
$calendar: 'content/calendar.json'
};
var settings = {};
var promises = [];
var appConfig = angular.module('app.settings', []);
angular.forEach(urlMap, function(url, key) {
promises.push($http.get(url).success(function(data) {
settings[key] = data;
}));
});
$q.all(promises).then(function() {
bootstrap(settings);
}).catch(function() {
bootstrap();
});
function bootstrap(settings) {
appConfig.value('Settings', settings);
angular.element(document).ready(function() {
angular.bootstrap(document, ['app', 'app.settings']);
});
}
});
[2] Assuming that the name of your main module is app within app.js:
angular.module('app', [])
.factory('DayService', function(Settings){
var calendar = Settings.$calendar,
season = calendar.seasons.season,
obj = {};
obj.season = function(d){
var day = new Date(d).getTime(),
start, end, value;
for (var i = 0; i < season.length; i++){
start = new Date(season[i].start);
end = new Date(season[i].end);
end.setHours(23,59);
if (day >= start && day <= end){
value = season[i].name;
break;
}
}
return value;
};
obj.weekInSeason = function(d){
var day = new Date(d).getTime(),
end, diff, start, startDiff, week;
for (var i = 0; i < season.length; i++){
end = new Date(season[i].end);
end.setHours(23,59);
end = end.getTime();
diff = end - day;
if (parseFloat(diff) > 0){
start = new Date(season[i].start);
start = start.getTime();
startDiff = day - start;
week = parseInt(startDiff /(1000*60*60*24*7))+1;
break;
}
}
return week;
};
return obj;
});
[3] Controller Usage(Example):
angular.module('app')
.controller('SampleController', function(DayService) {
console.log(DayService.season(3));
console.log(DayService.weekInSeason(3));
});
Another Note: Use .run() to check if Settings === null - if this is true, you can direct to an error page or any page that displays the problem(This means that the application bootstrapped but one of the requested configuration failed).
UPDATE:
I checked the link you have provided, and it seems that the version you are using is AngularJS v1.0.8, which does not have a .catch() method in their $q promise implementation.
You have the following options to consider in solving this problem:
-1 Change the AngularJS version you are using to the latest stable version 1.2.23.
Note that this option may break some of your code that is highly reliant on the version that you are using.
-2 Change this block:
$q.all(promises).then(function() {
bootstrap(settings);
}).catch(function() {
bootstrap();
});
to:
$q.all(promises).then(function() {
bootstrap(settings);
}, function() {
bootstrap();
});
This option is safer if you already have existing code that relies on the current AngularJS version you are using But I would suggest you change to the current stable version as it has more facilities and fixes than the one you are currently using.
Use your scope and closure of the factory to store the value of the response to the http call. I created an object called calData, which happens to already be a promise!
This gives you the ability to kick a few things off when the first call to the factory is made by running an IIFE (this is the function called initService), and everything chains together to resolve after the data is loaded.
.factory('dayService', function dayServiceFactory($http, $q){
var getCalData = $q.defer();
var calData = gettingData.promise; // null/undefined until _loadData is called and resolved
function _loadData(){
var deferred = $q.defer();
$http.get('content/calendar.json').success(function(data) {
calData.seasons = data.calendar.seasons; // your code seems to always use at least calendar.seasons, so easier to assign that
deferred.resolve(data);
});
return deferred.promise;
}
// this function will automatically run and load data the first time the factory is executed
(function initService(){
_loadData().then(){
// here is where you will build all your functions to assign properties to calData.seasons or any other child property of calData;
calData.getSeason = function(){
for (var i=0; i<data.calendar.seasons.season.length; i++){
// code here
}
}// function to get day using calData.seasons
calData.weekInSeason = function(){}
getCalData.resolve(); // this resolves the data in the outer scope
}
}());
return calData; // returns the promise, and will execute the first time called
});
To use this in a controller, make sure to either resolve the service before you instantiate the controller, or withing the controller, use your assignments of the data after it has resolved. (Bound values will auto-update when it's resolved)
dayService.then(function(){
// now you can use this:
var week = dayService.weekInSeason();
})
You can create separate method for getting calendar data and chain promises in getData method:
emmanuel.factory('DayService', ['$q', '$timeout', '$log',
function($q, $timeout, $log) {
return {
season: season,
weekInSeason: weekInSeason,
getData: getData
};
function season(d) {
$log.log('season called');
return getCalendar(d).then(function(calendar) {
return getSeason(d, calendar);
});
}
function weekInSeason(d) {
$log.log('weekInSeason called');
return getCalendar(d).then(function(calendar) {
return getWeekInSeason(d, calendar);
});
}
function getData(d) {
$log.log('getData called');
return getCalendar(d).then(
function(calendar) {
return $q.all({
season: getSeason(d, calendar),
weekInSeason: getWeekInSeason(d, calendar)
});
}
);
}
function getSeason(date, calendar) {
$log.log('getSeason called');
return {
date: date,
calendar: calendar,
method: 'getSeason'
};
}
function getWeekInSeason(date, calendar) {
$log.log('getWeekInSeason called');
return {
date: date,
calendar: calendar,
method: 'getWeekInSeason'
};
}
function getCalendar(d) {
$log.log('getCalendar called');
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(12345);
}, 2000);
return deferred.promise;
}
}
]);
Also, if calendar.json doesn't changed during application lifetime, you can cache calendar.json ajax request result as suggested by #runTarm
Plunker

NODEJS node-mysql cannot pass query results in nested queries

I am using node, angular and mysql, the node routes would return a json that would be processed by angular, the json is returned by first querying the mysql DB using the node-mysql module,
In the below code I am unable to set the value of CreatedID, but the value gets logged properly in terminal. I was facing the same issue in the 1st query but then sorted it in the below code, now unable to access the nested query results.
var mysql = require('node-mysql/node_modules/mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : "root",
password: "",
database:'designtaskmanager'
});
connection.connect();
var allDbCalls = function() {
var sendData = {};
var rowData = {};
var temp={};
var _this = this;
this.sendTask = function(callback) {
module.exports.taskData = rowData;
callback['success']();
};
this.getTask = function(callback) {
var strQuery = "select * from task";
connection.query( strQuery, function(err, rows){
if(err)
{
callback['failure']();
throw err;
}
else
{
//rowData = rows;
var tasks=[];
for (var i in rows)
{
var Title = rows[i].task_title;
var TaskDescription=rows[i].task_description;
var TaskCategory=rows[i].task_category;
var TaskID=rows[i].task_id;
var TaskStatus=rows[i].task_status;
var TaskStatusMessage
var CreatedBy;
var TaskCreationDate=rows[i].task_creation_date;
var _MS_PER_DAY = 1000 * 60 * 60 * 24;
var currentdate = new Date();
var ddd=dateDiffInDays(TaskCreationDate,currentdate);
function dateDiffInDays(a, b) {
// Discard the time and time-zone information.
var utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
var utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((utc2 - utc1) / _MS_PER_DAY);
}
if(TaskStatus==0)
{
TaskStatus="label-info";
TaskStatusMessage="Ongoing since";
}
else if(TaskStatus==1)
{
TaskStatus="label-default";
TaskStatusMessage="Paused since"
}
else if(TaskStatus==2)
{
TaskStatus="label-success";
TaskStatusMessage="Completed in"
}
//USER DETAILS QUERY
var crid=rows[i].task_created_by;
var creatorQuery = "select user_email from users where user_id like ?";
connection.query( creatorQuery,[crid], function(err, createdbyrows){
if(err)
{
callback['failure']();
throw err;
}
else
{
for(var j=0; j< createdbyrows.length;j++)
{
CreatedBy=createdbyrows[0].user_email;
console.log(j);
}
console.log(CreatedBy);
}
});
var taskItem={"TaskID":TaskID,"TaskTitle":Title,"TaskDescription":TaskDescription,"TaskCategory":TaskCategory,"CreatedBy":CreatedBy,"TaskStatus":TaskStatus,"TaskStatusMessage":TaskStatusMessage,"DifferenceInDays":ddd};
tasks.push(taskItem);
}
rowData=tasks;
_this.sendTask(callback);
}
});
}
}
module.exports = function () {
var instance = new allDbCalls();
return instance;
};
The reason that you're seeing it on the console but not in the callback is due to a misunderstanding of asynchronous programming. When you:
for(var i in rows) {}
You are actually queuing up all of those queries at the same time, then, immediately after you try to set rowData to an empty array:
rowData=tasks; // remember, none of the queries have finished yet
_this.sendTask(callback);
So you pretty much call your callback when tasks is still an empty array. Remember, you can't call your final callback until ALL of your nested queries have finished!
To accomplish this, you may want to look at the async library: https://github.com/caolan/async#eachSeries
This will help you accomplish what you really want.
var async = require("async");
async.eachSeries(rows, function(row, cb) {
// Do each query here
// then call cb() when done, which tells the async library
// to "go to the next item in the array"
}, function(err) {
// This will get called when all of the single queries are finished
// Check err, then call your callback
_this.sendTask(callback);
});