Javascript anonymous function question - javascript

I have this js class which has an anonymous function to retrieve some query results. Since the function which handles the results is anonymous I can't save the results in a this.var variable and use them somewhere else since this in the anonymous function references to the window object. I can't return it as a function return either so how do I do with those results to have them available somewhere else?
someObject = {
// this.db is created, no need to paste that code
dbGetAnimals: function () {
this.db.readTransaction(function(tx) {
tx.executeSql("SELECT * FROM animals", function(tx, results){
return results;
} )
});
},
printAllAnimals: function () {
var animals = this.dbGetAnimals();
alert (animals);// undefined
}
}
someObject.printAllAnimals();

You can create a local variable to hold your this reference. Your anonymous function will become a closure, so it will be able to see that local var.
dbGetAnimals: function () {
var myself = this;
this.db.readTransaction(function(tx) {
tx.executeSql("SELECT * FROM animals", function(tx, results){
myself.var = results;
} )
});
},

You're trying to do traditional synchronous/non-blocking programming where you want to do asynchronous programming.
var someObject = function()({
this.dbGetAnimals = function (callback) {
db.readTransaction(function(tx) {
tx.executeSql("SELECT * FROM animals", function(tx, results){
callback(results);
} )
});
},
this.printAllAnimals = function (callback) {
this.dbGetAnimals(callback);
}
})();
someObject.printAllAnimals(function(animals) {
alert(animals);
}
There are much cleaner ways to do this, but for async programming you have to learn to do everything on callbacks instead of direct returns.

This is happening because the anonymous function in executeSql is a callback function which is not executed until the query compmetes, which by definition will be after dbGetAnimals returns. That's why your call to dbGetAnimals is returning undefined.
You'll have to pass a callback function to receive the query resutls from within the executSql callback:
someObject = {
// this.db is created, no need to paste that code
dbGetAnimals: function (callback) {
this.db.readTransaction(function(tx) {
tx.executeSql("SELECT * FROM animals", function(tx, results){
callback(results);
} );
});
},
printAllAnimals: function () {
this.dbGetAnimals(function(animals) {
alert(animals)
});
}
}
someObject.printAllAnimals();

Related

JavaScript: Passing parameters to a callback function in "then" section

I'm trying to pass some parameter to a function used as callback, in "then" section. How can I do that?
In the following example, executionContext results as "undefined" in the callaback function.
function page_refresh(executionContext)
{
Xrm.Navigation.openAlertDialog({ text: "Now I'll refresh page"}).then(
function (success) {
var formContext = executionContext.getFormContext();
formContext.data.refresh(true);
},
function (error) {
console.log(error.message);
}
);
}

what does this function do when calling itself from within?

The following piece of code is a controller with crud operators for a model.
I cannot figure out what the Zone.find does when it calls itself in the function declaration and why it has to call itself.
var Zone = require('../models/Zone')
module.exports = {
find: function(params, callback){
Zone.find(params, function(err, zones){
if(err){
callback(err, null)
return
}
callback(null, zones)
})
},
findById: function(){
},
update: function(){
},
create: function(){
},
destroy: function(){
},
}
module.exports = {
find: function(params, callback){
and
Zone.find(params, function(err, zones){
are two seperate functions.
by calling Zone.find() invoke the find() function which is exported in Zone.js('../models/Zone') and the return value of that function is exported as the find() function of the controller

Stubbing async.waterfall with Sinon.JS

I am trying to test async.waterfall by stubbing one of my functions using Sinon.js.
// functions.js
module.exports = {
// function I don't want to run
doBigThing: function() {
console.log("[doBigThing] was called");
},
// function I want to stub
myFunction: function(number, callback) {
console.log("[myFunction] was called");
doBigThing();
callback(null, number);
},
// function I want to test
waterfall: function(callback) {
return async.waterfall([
async.constant(5), // 5 just for the demo
myFunction
], callback);
}
}
And my test is:
describe('water', function() {
it ('successfully falls', function() {
// function under test
var waterfall = functions.waterfall;
var callback = function(err, number) {
expect(err).to.be.null;
expect(number).to.equal(5);
};
// I would like this stub to run instead of functions.myFunction
sinon.stub(functions, 'myFunction', function(number, callback) {
console.log("[myFunction] stub was called");
callback(null, number);
});
waterfall(callback);
// I suppose this is happening: myFunction(5, callback)
expect(functions.myFunction.withArgs(5, callback)).to.have.been.called;
expect(callback).to.have.been.called;
});
});
So the test passes, but the stub is ignored, because doBigThing was called:
Water
✓ successfully falls
[myFunction] was called
[doBigThing] was called
Instead I would like to see
Water
✓ successfully falls
[myFunction] stub was called
I am probably missing out on something and I would appreciate your help.
You're stubbing functions object's method myFunction, but in waterfall method you're calling a myFunction function (I actually can't run your code in my environment, I get "ReferenceError: myFunction is not defined"). So this should work:
// functions.js
var functions = {
// function I don't want to run
doBigThing: function() {
console.log("[doBigThing] was called");
},
// function I want to stub
myFunction: function(number, callback) {
console.log("[myFunction] was called");
functions.doBigThing(); // CHANGE HERE
callback(null, number);
},
// function I want to test
waterfall: function(callback) {
return async.waterfall([
async.constant(5), // 5 just for the demo
functions.myFunction // CHANGE HERE
], callback);
}
};
module.exports = functions;

Using Typeahead with SignalR

I am attempting to use Typeahead with my SignalR implementation.
What is happening is my Hub is getting hit and returning the value, but my result after .done() is undifined. I cannot work out why?
Javascript
$(function () {
var search = $.connection.searchHub;
$.connection.hub.start().done(function () {
$('#searchBar').typeahead(null, {
minLength: 2,
// begin source
source: function (query, process) {
var suggestions = [];// my callback value
search.server.search(query)
.done(function (result) {
console.log(result);
$.each(result, function () {
console.log(result);
suggestions.push(this);
process(suggestions);//process is a callback method
});
}).fail(function (error) {
console.log(error);
process([]);//process is a callback method, don't know if this is necessary here, but will produce no suggestions
});
}
});
});
Hub:
[HubName("searchHub")]
public class SearchHub : Hub
{
public async Task Search(string query)
{
api = new MovieApi();
var result = await api.Search(query);
if (result.results != null)
{
Clients.Client(Context.ConnectionId).results(result.results[0].title);
}
else
{
Clients.Client(Context.ConnectionId).noResults("There are no search results!");
}
}
}
Your search method does not return anything so its not strange that its undefined. You need to change to Task<T> and return something
Also I can not see that you are subscribing to results or noResults? Like
search.client.results = function(result) {
console.log(result);
};
edit: Also its very strange to use SIgnalR for this, standard REST with request/response should be fine here

Using callback function with prototype functions

I am having trouble figuring out how to pass the objects method rather than sort "generic prototype" method when doing callback.
function Client() {
this.name = "hello";
}
Client.prototype.apiCall = function(method, params, callback) {
callback();
}
Client.prototype.onLogin = function(error, data) {
console.log(this.name);// undefined!!!!
}
Client.prototype.start = function() {
var self = this;
self.apiCall('rtm.start', {
}, self.onLogin) // passing of method like this does not work.
}
I am passing the onLogin method but well it does not work. This is code I have re-written. Previously I nested all methods inside the Client function but well, I learned that that is not the way to do it so now I am trying using prototype.
I know there is some solution "binding" the onLogin function inside the Client() function but well I want to understand the issue.
You need to bind the apiCalls context to the callback using bind:
Client.prototype.apiCall = function(method, params, callback) {
var bound = callback.bind(this);
bound();
}
Otherwise, the this within onLogin is set to the global object.
See Call, Apply And Bind for further details.
Basically .bind(obj) returns a function which, when called, will internally use (obj) as this.
So you create this bound and then you call it.
You can use call or apply to bind this, see snippet. I've modified your code for demonstration purposes. Hope it clarifies things for you
function Client() {
this.name = "hello";
}
Client.prototype = {
apiCall: function(method, params, callback) {
try {
var trial = method.call(this, params);
callback.apply(this, [null, trial]);
} catch (e) {
callback.apply(this, [e, null]);
}
},
onLogin: function(error, data) {
if (error) {
Helpers.report('<b style="color: red">' +
'An error occured!</b> <i>' +
error.message + '</i>')
} else {
Helpers.report(this.name, ' (data.result = ' + data.result + ')');
}
},
start: function() {
Helpers.useCSS(1);
// error from this.rtm.start
Helpers.report('Command: <code>', 'this.apiCall(this.rtm.start, {will: \'not work\'}, this.onLogin);','</code>');
this.apiCall(this.rtm.start, {will: 'not work'}, this.onLogin);
// this.rtm.works is ok
Helpers.report('<br>Command: <code>',
'this.apiCall(this.rtm.works, {will: \'work\'}, this.onLogin);',
'</code>');
this.apiCall(this.rtm.works, {
will: 'work'
}, this.onLogin);
},
// --------------------------------
// added rtm for snippet demo
rtm: {
start: function(params) {
return anerror;
},
works: function(params) {
return {
result: 'worked, <code>params: ' + JSON.stringify(params) + '</code>'
};
}
},
};
new Client().start(); //<= here
<script src="https://rawgit.com/KooiInc/Helpers/master/Helpers.js"></script>

Categories

Resources