getting undefined variable in Nodejs - javascript

I'm using Node to run this code
but when I run this code get the undefined return from leadid variable in get function :
call = {};
call.hangup = {
get: function(isOpen, ami, elastic, validator, growly, mysql, request){
var self = call.hangup;
this.isOpen = isOpen;
this.ami = ami;
this.elastic = elastic;
this.validator = validator;
this.growly = growly;
this.mysql = mysql;
this.request = request;
if(isOpen)
{
ami.on('hangup', function(evt){
var cause_status = parseInt(evt.cause);
var message = self.causeStatus(cause_status);
var channel = evt.channel;
var isDAHDI = validator.contains(channel,"DAHDI");
if((isDAHDI)&&(cause_status == 16))
{
var mobile = evt.calleridnum;
if(validator.isLength(mobile,11))
{
if(validator.matches(mobile,/^09/i))
{
var txtMessage = "";
var sending = "";
var leadid = self.searching(mobile, mysql, validator);
retrun leadid; /// get the undefined !!!!
}
}
}
});
}else {
console.log("Hangup's Event is OFF !");
}
},
searching: function(number, mysql, validator){
this.number = number;
this.mysql = mysql;
this.validator = validator;
var query = "{sql ...}";
mysql.query(query, function(err, rows, fields) {
if (err) throw err;
if(!validator.isNull(rows))
{
return rows[0].leadid;
}else {
return false;
}
});
},
};
module.exports = call;
this is how I call it in main file:
var call = require('./call');
call.hangup.get(true, ami, client, validator, growly, connection, request);
in other hands when I call this function (searching) in the main file
new call.hangup.searching(number, connection, validator);
it's work correctly
how can I fix it ?

You need to keep in mind that JavaScript is asynchronous.
When searching is called the database query is issued asynchronously and the function returns before the database would give you a result. In other words your searching function does not give you the result from
function(err, rows, fields) {
if (err) throw err;
if(!validator.isNull(rows))
{
return rows[0].leadid;
}else {
return false;
}
}
as you would desire,
searching: function(number, mysql, validator){
this.number = number;
this.mysql = mysql;
this.validator = validator;
var query = "{sql ...}";
mysql.query(query, function(err, rows, fields) {
if (err) throw err;
if(!validator.isNull(rows))
{
return rows[0].leadid;
}else {
return false;
}
});
--- > This is reached at the end of the call and nothing is returned },
};
it does not return explicitly anything, hence the undefined.
You should either use promises or pass in searching a callback function that will be called when your database query returns.
So your solution should look like this:
get: function (...){
...
self.searching(mobile, mysql, validator, whatIwantToDoAfterValidation)
},
searching: function(number, mysql, validator, callback){
...
mysql.query(..., callback){
if(!validator.isNull(rows))
{
callback(rows[0].leadid);
}else {
callback(false);
}
}
},
whatIwantToDoAfterValidation: function(leadid){
...do whatever you want with leadid...
}
Take a look at jquery's promises to do the same thing with promises.

Related

mvc asp can't update using query from my view

I am trying to have save changes on my script and I just need an update from my table. So far if I clicked the button, the alert success will not pop and can't see any error either. I also tried to verify to my table if the changes is made but the result is nothing happened
Here is the call function from my save button:
<script>
var op = '';
var op_dif = '';
$('#btnSave').click(function () {
op = $('#op').val();
op_dif = $('#op_difficulty').val();
alert(op + " " + op_dif); // I can see the value here
$.post("/Home/UpdateOP", {
'data': JSON.stringify([{
'op': op,
'opDiff': Op_dif
}])
}, function (data) {
var resp = JSON.parse(data);
if (resp["status"] == "SUCCESS") {
alert('Data has been successfully updated');
location.reload();
}
else {
alert('Error!!');
}
});
});
</script>
My view where my update query is located:
public string UpdateOpsDiff(operation[] ops)
{
string res = "";
foreach(var op in ops)
{
string updatetQuery = "update sys.OP_difficulty set op_difficulty = #diff where op = #op;";
MySqlCommand updateCommand = new MySqlCommand(updatetQuery);
updateCommand.Connection = myConnection;
updateCommand.Parameters.AddWithValue("#diff", op.op_dif);
updateCommand.Parameters.AddWithValue("#op", op.op);
myConnection.Open();
int updatedRowNum = 0;
try
{
updatedRowNum = updateCommand.ExecuteNonQuery();
}
catch(MySqlException)
{
updatedRowNum = updateCommand.ExecuteNonQuery();
}
finally
{
myConnection.Close();
}
res = "{status:SUCCESS, updatedRowNum:" + updatedRowNum + "}";
}
return res;
}
Controller where it reads the view query:
public string UpdateOp()
{
string data = Request.Form["data"];
IQA sys = new MysqlSys();
try
{
var rows = JsonConvert.DeserializeObject<operation[]>(data);
return sys.UpdateOpsDiff(rows);
}
catch (JsonSerializationException je)
{
Console.WriteLine(je.Message);
return "{status:'DATA_FORMAT_ERROR'}";
}
}
Is there any missing items that I need. It already working using the query from my controller but this time I need to store my query from my view.
Any suggestions or comments. TIA
Since you're using AJAX callback, you should change return type to ActionResult and mark the action method with [HttpPost] attribute, also you should use return Content() or return Json() depending on returned type from UpdateOpsDiff() (string or object, respectively). Here is an example of proper setup:
[HttpPost]
public ActionResult UpdateOp(string data)
{
IQA sys = new MysqlSys();
try
{
var rows = JsonConvert.DeserializeObject<operation[]>(data);
string result = sys.UpdateOpsDiff(rows);
// return JSON-formatted string should use 'Content()', see https://stackoverflow.com/q/9777731
return Content(result, "application/json");
}
catch (JsonSerializationException je)
{
// do something
return Json(new { status = "DATA_FORMAT_ERROR"});
}
}
Then set the AJAX callback to pass JSON string into action method mentioned above:
$('#btnSave').click(function () {
op = $('#op').val();
op_dif = $('#op_difficulty').val();
var values = { op: op, opDiff: op_dif };
$.post("/Home/UpdateOP", { data: JSON.stringify(values) }, function (data) {
var resp = JSON.parse(data);
if (resp["status"] == "SUCCESS") {
alert('Data has been successfully updated');
location.reload();
}
else {
alert('Error!!');
}
});
});
Note:
The JSON-formatted string should be presented in key-value pairs to be returned as content, as shown in example below:
res = string.Format(#"{""status"": ""SUCCESS"", ""updatedRowNum"": ""{0}""}", updatedRowNum);

Cloud function returning nil value

I had a freelancer do some work in cloud code however I can no longer contact them due to an argument that occurred. I do not know javascript nor am I familiar with Parse cloud code and I was hoping someone could shed light on whether or not I am calling this function correctly considering it returns as if its parameter was equal to nil although I do believe I am giving it a value. Below is the javascript cloud code function as well as my swift code where I am calling it. For instance it is returning the value (-5).
Parse.Cloud.define("AddFriendRequest", function (request, response) {
var FriendRequest = Parse.Object.extend("FriendsIncoming");
var FRequest = new FriendRequest();
var user = request.user;
var query = new Parse.Query(Parse.User);
query.equalTo("username", request.params.username);
query.find({
success: function (people) {
if(people.length == 0)
{
response.success(-5);
return;
}
var person = people[0];
FRequest.set("OwnerID", user.id);
FRequest.set("TargetFriend", person.id);
FRequest.set("Status", 0);
var query = new Parse.Query("FriendsIncoming");
query.equalTo("OwnerID", user.id);
query.equalTo("TargetFriendID", person.id);
query.find({
success: function (results) {
if (results.length > 0) {
response.success(1);
return;
}
FRequest.save(null, {
success: function (Friend) {
response.success(2);
},
error: function (Friend, error) {
response.error(3);
}
});
response.error(-2);
},
error: function () {
response.error(-1);
}
});
}
,
error: function (Friend, error) {
response.error(-4);
}
});
});
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == NewRequest {
textField.resignFirstResponder()
print(NewRequest)
var name : NSString
name = NewRequest.text!
print(name)
//let parameters : [NSObject : AnyObject]
let params = ["TargetFriendID" : name]
PFCloud.callFunctionInBackground("AddFriendRequest", withParameters: params) { results, error in
if error != nil {
//Your error handling here
} else {
print(results)
}
}
return false
}
return true
}
The parameter from the client is named "TargetFriendID", but the cloud function runs the query on request.params.username.
Either rename the parameter in swift to username, or rename the parameter in the cloud to request.params.TargetFriendID.

Controller is executing before the factroy is giving result [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
with reference to this answer How do I return the response from an asynchronous call? how could i implement this one in my secanrio.
I am trying to do caching with use of sqlite using cordova sqlite plugin but my problem is my controller executes before my factory completes its execution. I am pasting my controller code and my factory code. I had put alert for knowing the sequence of execution. My ideal alert sequence is 1,2,3,4,5,6 but when i am executing the code i am getting alert sequence like 1,5,6,2,3,4. I am pasting my controller and factory code below.
angular.module('foo').controller('PriceListController',["$scope","$http","$stateParams","CURD","$q","DB", function($scope,$http,$stateParams,CURD,$q,DB) {
$scope.brand_id=Number($stateParams.id);
$scope.process=true;
$scope.pricelists=[];
$scope.getBrandDocs= function(){
var parameters=new Array(2);
parameters[0]=$scope.brand_id
parameters[1]=1;
CURD.exc_query("select * from brand_docs where brand_id=? AND type=?",parameters)
.then(function(price_lists) {
alert("2");
$scope.inter_pricelist=price_lists;
console.log("Records from query call:"+JSON.stringify( $scope.inter_pricelist));
$scope.deferred = $q.defer();
if ($scope.inter_pricelist){
console.log("Found data inside cache", JSON.stringify($scope.inter_pricelist));
$scope.deferred.resolve($scope.inter_pricelist);
// alert(JSON.stringify( $scope.inter_pricelist));
alert("3");
}
else{
$http.get('http://foo.com?brand='+ $scope.brand_id +'&type=price_list')
.success(function(data) {
//alert("http call");
console.log("Received data via HTTP",JSON.stringify(data));
angular.forEach(data.data.info, function(value, key) {
var sql = "INSERT OR REPLACE INTO brand_docs(id, brand_id, name, file_url,type) VALUES (?, ?, ?, ?, ?)";
var parameters=new Array(5);
parameters[0]=value.id;
parameters[1]=value.brand_id;
parameters[2]=value.name;
parameters[3]=value.file_url;
parameters[4]=value.type;
var result=DB.query(sql,parameters);
});
$scope.deferred.resolve(data.data.info);
})
.error(function() {
console.log("Error while making HTTP call.");
$scope.deferred.reject();
});
}
return ($scope.deferred.promise).then(function(pricelists){
alert("4");
return pricelists;
},function(){});
},function(){});
alert("5");
};
$scope.pricelists=$scope.getBrandDocs();
alert("6");
}]);
// This is factory code i am pasting
angular.module('foo').factory('DB', function($q, DB_CONFIG,$cordovaSQLite) {
var self = this;
self.db = null;
self.init = function() {
try{
self.db = window.sqlitePlugin.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);
angular.forEach(DB_CONFIG.tables, function(table) {
var columns = [];
angular.forEach(table.columns, function(column) {
columns.push(column.name + ' ' + column.type);
});
var query = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';
self.query(query);
console.log('Table ' + table.name + ' initialized');
});
}
catch(err){
}
};
self.query = function(query, bindings) {
bindings = typeof bindings !== 'undefined' ? bindings : [];
console.log("Query:"+query+" bindings:"+ bindings);
var deferred = $q.defer();
self.db.transaction(function(transaction) {
transaction.executeSql(query, bindings, function(transaction, result) {
console.log("Query sucessfull :"+ query);
console.log("Result of Query:"+ JSON.stringify(result));
deferred.resolve(result);
}, function(transaction, error) {
console.log("Error:"+ JSON.stringify(error));
deferred.reject(error);
});
});
return deferred.promise;
};
self.fetchAll = function(result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
//console.log("RECORDS:" +JSON.stringify(output));
return output;
};
self.fetch = function(result) {
return result.rows.item(0);
};
return self;
})
.factory('CURD', function(DB) {
var self = this;
self.all = function(table_name) {
return DB.query('SELECT * FROM '+table_name)
.then(function(result){
return DB.fetchAll(result);
});
};
self.exc_query = function(query,parameters) {
return DB.query(query,parameters)
.then(function(result){
return DB.fetchAll(result);
});
};
self.getById = function(id,table_name) {
return DB.query('SELECT * FROM '+table_name +' WHERE id = ?', [id])
.then(function(result){
return DB.fetch(result);
});
};
return self;
});
The query completes asynchronously. By that I mean that when you call CURD.exec_query(), the query is queued and as soon as it is queued, your method continues to execute at "return ($scope.deferred.promise).then(function(pricelists){". That's why 4, 5, 6 show up before 2 and 3. Once the query completes, again, asynchronously, the ".then()" method is called, which is when 2 and 3 are alerted.
Note that getBrandDocs() is going to return BEFORE then .then() method is called. What you could do is have your .then() method emit an event that is asynchronously picked up in the calling code which would in turn execute the 4, 5, and 6 steps.

Trying to get an async DB request to work in Angular, "Cannot call method then of undefined"

I'm building a PhoneGap app using AngularJS + an SQLite database. I am having a classic "How does asynchronous work" Angular problem with a database query, getting error "Cannot call method then of undefined". I am hoping someone can help me to see the error of my ways.
Here's my query function. Every alert() in here returns meaningful data indicating that the transaction itself is successful:
.factory('SQLService', ['$q', '$rootScope', 'phonegapReady',
function ($q, $rootScope, phonegapReady) {
function search(query) {
alert("Search running with " + query);
var promise = db.transaction(function(transaction) {
var str = "SELECT category, id, chapter, header, snippet(guidelines, '<b>', '</b>', '...', '-1', '-24' ) AS snip FROM guidelines WHERE content MATCH '" + query + "*';";
transaction.executeSql(str,[], function(transaction, result) {
var resultObj = {},
responses = [];
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
resultObj = result.rows.item(i);
alert(resultObj.category); //gives a meaningful value from the DB
responses.push(resultObj);
}
} else {
//default content
}
},defaultNullHandler,defaultErrorHandler);
alert("End of transaction");
});
// Attempting to return the promise to the controller
alert("Return promise"); //this alert happens
return promise;
}
return {
openDB : openDB,
search: search
};
}]);
And in my controller, which gives the "Cannot call method then of undefined" error:
$scope.search = function(query) {
SQLService.search(query).then(function(d) {
console.log("Search THEN"); //never runs
$scope.responses = d; //is never defined
});
}
Thanks to the accepted answer, here is the full working code.
Service
function search(query) {
var deferred = $q.defer();
db.transaction(function(transaction) {
var str = "SELECT category, id, chapter, header, snippet(guidelines, '<b>', '</b>', '...', '-1', '-24' ) AS snip FROM guidelines WHERE content MATCH '" + query + "*';";
transaction.executeSql(str,[], function(transaction, result) {
var resultObj = {},
responses = [];
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
resultObj = result.rows.item(i);
responses.push(resultObj);
}
} else {
resultObj.snip = "No results for " + query;
responses.push(resultObj)
}
deferred.resolve(responses); //at the end of processing the responses
},defaultNullHandler,defaultErrorHandler);
});
// Return the promise to the controller
return deferred.promise;
}
Controller
$scope.search = function(query) {
SQLService.search(query).then(function(d) {
$scope.responses = d;
});
}
I can then access the responses in the template using $scope.responses.
The question here is: what does db.transaction return.
From the way you're using it, I'm guessing it's some 3rd-party code that doesn't return a promise.
Assuming that you're using it correctly (your alert shows the right results), you need to actualy use $q to get the promise working.
Something like this:
function search(query) {
// Set up the $q deferred object.
var deferred = $q.defer();
db.transaction(function(transaction) {
transaction.executeSql(str, [], function(transaction, result) {
// do whatever you need to do to the result
var results = parseDataFrom(result);
// resolve the promise with the results
deferred.resolve(results);
}, nullHandler, errorHandler);
});
// Return the deferred's promise.
return deferred.promise;
}
Now, in your controller, the SQLService.search method will return a promise that should get resolved with the results of your DB call.
You can resolve multiple promises. Pass the array of queries as args
function methodThatChainsPromises(args,tx){
var deferred = $q.defer();
var chain = args.map(function(arg){
var innerDeferred = $q.defer();
tx.executeSql(arg,[],
function(){
console.log("Success Query");
innerDeferred.resolve(true);
},function(){
console.log("Error Query");
innerDeferred.reject();
}
);
return innerDeferred.promise;
});
$q.all(chain)
.then(
function(results) {
deferred.resolve(true)
console.log("deffered resollve"+JSON.stringify(results));
},
function(errors) {
deferred.reject(errors);
console.log("deffered rejected");
});
return deferred.promise;
}

Trying to get HTTP POST request in Firefox extension

I'm building an extension to get the POST request in Firefox. I read through the documentation for intercepting page loads and HTTP observers, but still couldn't manage to get the specific POST data on a page load (ex: data1=50&sdata2=0&data3=50).
I looked into TamperData's code, and found that they used stream.available() and stream.read(1). However, I couldn't get these commands to work with my code.
Currently my code looks like this:
var ObserverTest = {
observe: function(subject, topic, data) {
if (topic == 'http-on-modify-request') {
var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
}
if (topic == "http-on-examine-response") {
var newListener = new TracingListener();
subject.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = subject.setNewListener(newListener);
}
},
register: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.addObserver(ObserverTest, "http-on-modify-request", false);
observerService.addObserver(ObserverTest, "http-on-examine-response", false);
},
unregister: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(ObserverTest, "http-on-modify-request");
observerService.removeObserver(ObserverTest,"http-on-examine-response");
}
}
window.addEventListener("load", ObserverTest.register, false);
window.addEventListener("unload", ObserverTest.unregister, false);
//Helper function for XPCOM instanciation (from Firebug)
function CCIN(cName, ifaceName) {
return Cc[cName].createInstance(Ci[ifaceName]);
}
// Copy response listener implementation.
function TracingListener() {
this.originalListener = null;
this.receivedData = []; // array for incoming data.
}
TracingListener.prototype = {
onDataAvailable: function(request, context, inputStream, offset, count) {
var binaryInputStream = CCIN("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
var storageStream = CCIN("#mozilla.org/storagestream;1", "nsIStorageStream");
var binaryOutputStream = CCIN("#mozilla.org/binaryoutputstream;1", "nsIBinaryOutputStream");
var stream = Components.classes["#mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
stream.init(binaryInputStream);
binaryInputStream.setInputStream(inputStream);
storageStream.init(8192, count, null);
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), offset, count);
},
onStartRequest: function(request, context) {
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode)
{
// Get entire response
var responseSource = this.receivedData.join();
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
}
}
First of all, the "http-on-examine-response" and TracingListener isn't required at all. This stuff would have merit if you wanted to do something with the response, but you're after data in the request, so topic == 'http-on-modify-request' it is.
The following function (untested, but copied from one of my extensions and cleaned up a bit) demonstrates how to get post data. The function is assumed to be called from http-on-modify-request.
const ScriptableInputStream = Components.Constructor(
"#mozilla.org/scriptableinputstream;1",
"nsIScriptableInputStream",
"init");
function observeRequest(channel, topic, data) {
let post = null;
if (!(channel instanceof Ci.nsIHttpChannel) ||
!(channel instanceof Ci.nsIUploadChannel)) {
return post;
}
if (channel.requestMethod !== 'POST') {
return post;
}
try {
let us = channel.uploadStream;
if (!us) {
return post;
}
if (us instanceof Ci.nsIMultiplexInputStream) {
// Seeking in a nsIMultiplexInputStream effectively breaks the stream.
return post;
}
if (!(us instanceof Ci.nsISeekableStream)) {
// Cannot seek within the stream :(
return post;
}
let oldpos = us.tell();
us.seek(0, 0);
try {
let is = new ScriptableInputStream(us);
// we'll read max 64k
let available = Math.min(is.available(), 1 << 16);
if (available) {
post = is.read(available);
}
}
finally {
// Always restore the stream position!
us.seek(0, oldpos);
}
}
catch (ex) {
Cu.reportError(ex);
}
return post;
}
Depending on your use case, you might want to check if the us instanceof e.g. nsIMIMEInputStream or nsIStringInputStream for special handling or fast-paths...
You'd call it from your observer like:
observe: function(subject, topic, data) {
if (topic == 'http-on-modify-request') {
observeRequest(subject, topic, data);
}
},

Categories