In my AngularJS controller, I have the following code:
$scope.readMDB = function () {
var fs = require('fs');
var adodb = require('node-adodb');
var password = document.forms["mdbSelForm"]["pwd"].value;
var revSQL = fs.readFileSync('revenue.sql', 'utf-8');
revSQL = revSQL.replace(/(\r\n|\n|\r)/gm, " ");
revSQL = revSQL.replace(/[รค]/g, function () { return unescape("%E4") });
$scope.revenueSQL = String(revSQL);
console.log("revSQL: " + $scope.revenueSQL);
connection = adodb.open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' + $scope.selectedMDB + ';Jet OLEDB:Database Password=' + password + ';');
// debug
adodb.debug = true;
connection
.query($scope.revenueSQL)
.on('done', function (data) {
var revAll = JSON.stringify(data);
var revenueData = JSON.parse(revAll).records;
fs.writeFile('./model/revenue.json', JSON.stringify(data), function (err) {
if (err) throw err;
console.log("revenue.json saved");
});
return true;
})
.on('fail', function (data) {
return false;
});
}
A similar code worked fine while not using Angular. Now, it doesn't work no more, because of the
connection.query($scope.revenueSQL)
part. More precisely, the $scope.revenueSQL is not recognized as the SQL Statement that it actually is. Putting the SQL directly, without reading it from a file, works fine. Still, looking at my console, I see that $scope.revenueSQL is exactly what I want. But being put as parameter into .query(), something seems to go wrong. Any ideas?
Try
$scope.revenueSQL = $scope.$eval(String(revSQL));
to execute the expression on the current scope and returns the result.
Related
I'm new to learning Node.js, so I'm still getting used to asynchronous programming and callbacks. I'm trying to insert a record into a MS SQL Server database and return the new row's ID to my view.
The mssql query is working correctly when printed to console.log. My problem is not knowing how to properly return the data.
Here is my mssql query - in addJob.js:
var config = require('../../db/config');
async function addJob(title) {
var sql = require('mssql');
const pool = new sql.ConnectionPool(config);
var conn = pool;
let sqlResult = '';
let jobID = '';
conn.connect().then(function () {
var req = new sql.Request(conn);
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
jobID = result['recordset'][0]['JobID'];
conn.close();
//This prints the correct value
console.log('jobID: ' + jobID);
}).catch(function (err) {
console.log('Unable to add job: ' + err);
conn.close();
});
}).catch(function (err) {
console.log('Unable to connect to SQL: ' + err);
});
// This prints a blank
console.log('jobID second test: ' + jobID)
return jobID;
}
module.exports = addJob;
This is my front end where a modal box is taking in a string and passing it to the above query. I want it to then receive the query's returned value and redirect to another page.
// ADD NEW JOB
$("#navButton_new").on(ace.click_event, function() {
bootbox.prompt("New Job Title", function(result) {
if (result != null) {
var job = {};
job.title = result;
$.ajax({
type: 'POST',
data: JSON.stringify(job),
contentType: 'application/json',
url: 'jds/addJob',
success: function(data) {
// this just prints that data is an object. Is that because I'm returning a promise? How would I unpack that here?
console.log('in success:' + data);
// I want to use the returned value here for a page redirect
//window.location.href = "jds/edit/?jobID=" + data;
return false;
},
error: function(err){
console.log('Unable to add job: ' + err);
}
});
} else {
}
});
});
And finally here is the express router code calling the function:
const express = require('express');
//....
const app = express();
//....
app.post('/jds/addJob', function(req, res){
let dataJSON = JSON.stringify(req.body)
let parsedData = JSON.parse(dataJSON);
const addJob = require("../models/jds/addJob");
let statusResult = addJob(parsedData.title);
statusResult.then(result => {
res.send(req.body);
});
});
I've been reading up on promises and trying to figure out what needs to change here, but I'm having no luck. Can anyone provide any tips?
You need to actually return a value from your function for things to work. Due to having nested Promises you need a couple returns here. One of the core features of promises is if you return a Promise it participates in the calling Promise chain.
So change the following lines
jobID = result['recordset'][0]['JobID'];
to
return result['recordset'][0]['JobID']
and
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
to
return req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
and
conn.connect().then(function () {
to
return conn.connect().then(function () {
You may need to move code around that is now after the return. You would also be well served moving conn.close() into a single .finally on the end of the connect chain.
I recommend writing a test that you can use to play around with things until you get it right.
const jobId = await addJob(...)
console.log(jobId)
Alternatively rewrite the code to use await instead of .then() calls.
Basically, my code here is saying that if a user sends a message !submit ___ then the file leaderboard.json will up their count by one.
This all works perfectly however say for example their count goes from 0 to 1, the next time that same person sends !submit, their count should go from 1 to 2 without me having to restart the script every time. This isn't happening unfortunately... I send !submit and my count goes from 0 to 1, but then I send it again and it stays going from 0 to 1.
Leaderboard.json:
{
"usercount<#386679122614681600>": 0
}
index.js:
client.on('message', msg => {
if (msg.content.startsWith("!submit ")){
var shoe = msg.content.substr("!submit ".length);
var fs = require('fs')
fs.readFile('leaderboard.json', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
var user = msg.member;
var usercount = 'usercount'+user
var username = 'usercount'+user
var LEADERBOARD = require('./leaderboard.json');
var countvalue = LEADERBOARD[username]
var countvalue2 = countvalue+1
var replacetext = ('"'+usercount+'": '+countvalue).toString()
var newtext = ('"'+usercount+'": '+(countvalue2)).toString()
fs.writeFile('leaderboard.json', data.replace(replacetext, newtext),
'utf8', function () {
if (err) return console.log(err);
});
console.log('NEW SUBMISSION: '+replacetext+' >>>> '+newtext)
});
}
Here is what my console looks like after sending !submit twice:
When technically the second line should go from 1 to 2, without me having to close and restart the script.
I know this may seem a bit complicated but any help would be appreciated!
This is what I'd suggest:
const fs = require('fs')
client.on('message', msg => {
if (msg.content.startsWith("!submit ")) {
let shoe = msg.content.substr("!submit ".length);
// read leaderboard file and parse the JSON into a Javascript object
fs.readFile('leaderboard.json', 'utf8', function(err, data) {
if (err) {
console.log("Error reading leaderboard.json", err);
return;
}
let leaderboard;
try {
leaderboard = JSON.parse(data);
} catch(err) {
console.log("Error parsing leaderboard JSON", err);
return;
}
const user = msg.member;
const username = 'usercount' + user;
// make sure there's a count for this username
let cnt = leaderboard[username];
if (!cnt) {
cnt = 0;
}
// increment the cnt
++cnt;
// set the new count
leaderboard[username] = cnt;
// now write the data back to the file
fs.writeFile('leaderboard.json', JSON.stringify(leaderboard), 'utf8', function() {
if (err) {
console.log(err);
return;
}
console.log(`New Submission for ${username}, cnt = ${cnt}`);
});
});
}
});
Summary of changes:
Reads leaderboard.json only once using fs.readFile()
After reading the data, it converts it to JSON using JSON.parse().
Initializes user cnt if not already in the file
Updates cnt in the Javsacript object directly
Writes out the changed object using JSON.stringify() to convert the object back to JSON
Puts new submission console message in fs.writeFile() success handler
Switch to const and let from var
Issues not yet incorporated:
Concurrency issues if multiple message events can be "in-flight" at once and conflict.
More complete error handling besides just stopping processing when there's an error (I'm not sure what your application should be doing in that case as that is application-specific).
Your shoe variable is not being used anywhere, not sure what it's doing there.
How can I refractor my code to get rid of this error from JSLinter?
I tried moving the entire function out to a var but the code wasn't able to run after that.
for (i = 0; i < timeDifference; i++) {
timestamp ++;
console.log(timestamp);
energyDatum.find({timestamp: timestamp}).toArray(function(err, result) {
var data = {};
result.forEach(function(element) {
data[element.deviceId] = element;
});
var roomRawData = [];
mappings.forEach(function(room) {
var hash = {};
hash.floor = room.floor;
hash.name = room.name;
hash.room_type = room.room_type;
hash.energy_ac = sumApplianceEnergy('energy_ac', room, data);
hash.energy_light = sumApplianceEnergy('energy_light', room, data);
hash.energy_socket_1 = sumApplianceEnergy('energy_socket_1', room, data);
hash.energy_socket_2 = sumApplianceEnergy('energy_socket_2', room, data);
hash.energy_socket_3 = sumApplianceEnergy('energy_socket_3', room, data);
hash.energy_total = hash.energy_ac + hash.energy_light + hash.energy_socket_1 + hash.energy_socket_2 + hash.energy_socket_3;
hash.timestamp = timestamp;
roomRawData.push(hash);
});
roomRaw.insert(roomRawData, {w:1}, function(err, result) { console.log('done'); });
});
lastTimestamp.update({_id: timestampId}, {timestamp: timestamp});
}
JSLinter shows this message because your code has potential errors.
Take a look at this line:
energyDatum.find({timestamp: timestamp}).toArray(...);
This method is async, right? It means that the callback of toArray method
is called after the for loop finishes its iterations, and therefore timestamp
variable (when you use it inside this callback) doesn't have a value of current iteration,
but instead it has value incremented for timeDifference times.
To solve this problem you could move this callback to another function:
var getIterationFunc = function(timestamp) {
return function(err, result) {
var data = {};
// rest of function ...
}
}
and then use it:
energyDatum.find({timestamp: timestamp}).toArray(getIterationFunc(timestamp));
I believe this error should be fixed now. Hope this helps.
P.S. sorry for my English
So I have this model :
'use strict';
var mongoose = require('mongoose');
var subscriberModel = function () {
var subscriberSchema = mongoose.Schema({
email: String
});
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
subscriberSchema.methods.validateSubscriber = function (subs, otherModel) {
var code = 0;
if (validateEmail(subs.email)) {
mongoose.model('Subscriber').findOne({'email': subs.email},
function(err, subscriber){
if (err) {
code = 2;
} else if (subscriber) {
code = 3;
} else {
subs.save(function(err){
if (err) {
code = 2;
}
code = 4;
});
}
});
} else {
code = 1;
}
};
return mongoose.model('Subscriber', subscriberSchema);
};
module.exports = new subscriberModel();
And I call it in another file that way :
var subscriberModel = require('../models/subscriber');
var subscriber = new subscriberModel({email: req.body.email.trim()});
var code = subscriber.validateSubscriber(subscriber, buyModel);
console.log('code = %s', code); // => displays "code = 0"
I guess it's a scope problem or something like that (because I don't use any callback -or maybe I should-) but I can't find nor the problem, nor the solution.
So, how can I get the returned code value ?
Thanks in advance.
[EDIT] : I found where the problem was and edited the code to explain it. So apparently my var is set in the callbacks of mongoose so now my question is; how do I wait for this callback to end as I need the result to display a message to the user in a webpage?
Okay so, I found the answer.
I edited my function validateSubscriber to send a callback: subscriberSchema.methods.validateSubscriber = function (subs, callback). And removed the otherModel occurences inside.
That way, when I call it in my other file I just have to do :
subscriber.validateSubscriber(subscriber, function(code){
buyModel.code = code;
console.log('code = %s', buyModel.code);
}
To get the code AND wait for the answer.
I hope it helped someone else.
I am trying write a restapi using express framework and node.js. I am facing an error which I am unable to find out the root cause. I am getting the following error while trying to execute the code :
TypeError: Cannot read property 'node_type' of undefined where 'node_type' is a value that comes from a function
var GdbProcess = require('../../dao/gdb/processnds')
var mongo = require('mongodb');
var async = require('async');
exports.executeService = function(req,res){
//Make the process object to query
var manualProcessQuery = new Object();
manualProcessQuery.index = req.params.processmap;
manualProcessQuery.key = "pid";
manualProcessQuery.value = req.params.pid;
manualProcessQuery.event = req.params.event;
var tempDataNodeToExecute = new Object();
//This function returns an object (dataNodeToExecute) to execute
GdbProcess.getParametersbyNode(manualProcessQuery,function(err,dataNodeToExecute){
if(err) res.send(err);
tempDataNodeToExecute = dataNodeToExecute;
var isSystem = false;
if (tempDataNodeToExecute.node_type =="system"){
isSystem = true;
}
var count = 0;
async.whilst(
function () { return isSystem },
function (callback) {
//execute the function
executeSystem(dataNodeToExecute,function(err,executionStatus){
if (err) callback(err);
count++;
if(executionStatus=="completed"){
manualProcessQuery.value = tempDataNodeToExecute.pid;
manualProcessQuery.event = "completed";
GdbProcess.getParametersbyNode(manualProcessQuery,function(err,dataNodeToExecute2){
if(err) callback(err);
tempDataNodeToExecute = dataNodeToExecute2;
if (tempDataNodeToExecute.node_type == "manual"){
isSystem = false;
}
});
callback();
}
});
},
function (err) {
if(err) res.send(err);
res.send("success");
}
);
});
}
var executeManual = function(prosNodeToExecute,callback){
//do something
callback (null);
}
var executeSystem = function(prosNodeToExecute,callback){
//do something
callback(null,"completed");
}
When I debug the code, i clearly see that node_type is available. Can someone help me to find the root problem here ?
remove the new object tempDataNodeToExecute and use dataNodeToExecute instead of it, and it is a good practice to check for null of an object before using its property so that the program does not crashes.