trying to use a closure with parameters as a callback - javascript

I have a library function that I'm calling from a method. It takes a callback with one parameter that I would like to be another method from the same object. I can't seem to get the syntax right. Here's what I've got:
myOriginalObject.login = function() {
// inside a method
var obj = this;
var closure = function(token) { return function() { obj._login2(token); } }
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, closure );
// .. some more code and method ends
}
myOriginalObject._login2 = function(authResult)
{
// .. I can't get this function called by the gapi library
}
P.S. sorry if this post isn't done properly (still learning) thanks!!!

You're passing a reference to the closure function to authorize, but I think you want to call it and pass the reference to the function it creates. So:
// `token` argument here ------------------v
var closure = function() { return function(token) { obj._login2(token); } }
// not here------------^
and
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, closure() );
// Call it -----------------------------------------------^^
You may not need the closure function at all, but it's hard to tell without knowing more about the surrounding code. But this may well be all you need:
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, function(token) {
obj._login2(token);
});
Side note: Since myOriginalObject is a singleton, you don't need the var obj = this;, you can just use the symbol myOriginalObject directly:
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, function(token) {
myOriginalObject._login2(token);
});

This line:
var closure = function(token) { return function() { obj._login2(token); } }
will return a function, i.e. the return value of closure() is a function.
One solution:
change
var closure = function(token) { return function() { obj._login2(token); } }
to
var closure = function(token) { obj._login2(token); }

Related

Using $timeout in service: this.func is not a function

I've been trying to use promise to end user session after certain amount of time.
Problem is, whenever a function defined in service is called from the function triggered by $timeout, the function seems to be undefined. I think it's some kind of a scope issue, but I have not managed to fix this on my own.
app.service('sessionService', function($timeout) {
var closeSession = function() {
this.resetUserInfo()
// maybe do other things as well
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
this.resetUserInfo = function() {
// reset session
}
}
Error: this.resetUserInfo is not a function
Things I have tried
different ordering of functions
this.closeSession instead of var
$timeout(function(){closeSession(this.resetUserInfo)}, sessionLength) with proper modifications to closeSession
Note this assigned to that. So you are using the scope of the service instead of the scope of the method.
app.service('sessionService', function($timeout) {
var that = this;
var closeSession = function() {
that.resetUserInfo()
// maybe do other things as well
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
this.resetUserInfo = function() {
// reset session
}
}
An alternative would be to make resetUserInfo a local function and then attach to it this later on. For example:
app.service('sessionService', function($timeout) {
//private definition
var resetUserInfo = function() {
}
var closeSession = function() {
resetUserInfo(); //call the private version
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
//now expose method as public here
this.resetUserInfo = resetUserInfo;
}

How to dynamically change a function

I have a function that has already been assigned and I would like to append some additional script. When I display the function like:
var func = obj.when_clicked;
alert(func);
The following is displayed:
function object_123(){
object_123_Action();
}
The type is a "function" and the function is executed elsewhere which I cannot change, the code is:
this.when_clicked();
I need to modify the function by appending my own code so it becomes:
function object_123(){
object_123_Action();
my_clicked(obj);
}
Then add that back and over write the when_clicked function.
It does work if I manually add the code like:
obj.when_clicked = function object_123(){object_123_Action();my_clicked(obj);};
However, I do not know what is in the function initially, all I want is to append the:
my_clicked(obj);
I do need the obj to be the actual object of interest which is obj.
You can wrap it:
var f = this.when_clicked;
this.when_clicked = function() {
// Call the original
var rv = f.apply(this, arguments);
// your code here
// Return the original function's return value
return rv;
};
Function#apply calls the original with the specified this flag. arguments is provided by the JavaScript engine: It's a pseudo-array of the arguments your function was called with, so the above just passes all of them on.
Be sure to think about what it means if your function throws an exception, and catch them if you want to suppress them.
If you do this often, you can giev yourself a utility function:
function wrapFunction(f, wrapper) {
return function() {
var rv = f.apply(this, arguments);
wrapper.apply(this, arguments);
return rv;
};
}
Then
this.when_clicked = wrapFunction(this.when_clicked, function() {
// Your code here
});
Or if you want access to the original's return value, potentially changing it:
function wrapFunction(f, wrapper) {
return function() {
var rv = f.apply(this, arguments);
rv = wrapper.call(this, rv, arguments);
return rv;
};
}
Then
this.when_clicked = wrapFunction(this.when_clicked, function(rv, args) {
// Your code here, using `rv` and `args`, which is a pseudo-array
// Potentially update `rv`
return rv;
});
You can store your functions in an array on the object.
Then, loop though the functions in another function and execute them.
var myObj = { 'myfunctions': [ ] };
and to add functions:
myObj.myFunctions.push (function () { /*function code here*/ });
Or if you already have a named function:
myObj.myFunctions.push (nameOfFunction);
And to call all the functions, use this function (don't add this function to myObj)
function executeMyFunctions (myObj) {
for (var i = 0; i < myObj.myFunctions.length; i++) {
myObj.myFunctions[i]();
}
}
Used this answer on another question of #peter. Meant to post here.

making a function in an object chainable

I am trying to achieve a chainable object, but cannot figure out how I can do this within a function.
This is how I would like it to work:
$donate.ga('testing').go(value);
My object currently looks like this:
var $donate = {
ga: function (value) {
}
};
You simply need to make each function to return the instance of the object:
var $donate = {
ga: function (value) {
// logic
return this;
}
};
It's already solved here. You must simply return the object in your function.
You need to return the Object like that:
var $donate = {
ga: function (value) {
//after some computation
return this;
},
go: function(val) {
//after some computation
return this;
}
};
If you don't return this (this is a reference to the current Object), you either return undefined or something else and your method defined in your Object is simply out of scope (unknown).
you have to return this; in each sub function before closing it.
for example
Your code
var $donate = {
ga: function (value) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
},
go: function(val) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
}
};

I wanted to make a javascript library function is not working

I wanted to call the run function that should call the other and action will be done on the base of element_id
NGL = {}
NGL.SceneBuilder = function() {
var yamlFile = 'http://example.com/main.yaml'
var parseYaml = function() {
}
var buildScene = function() {
// other code
simulationStarted(element_id);
}
return {
run: function(element_id) {
parseYaml();
buildScene(element_id);
}
}
}
NGL.SceneBuilder.run('#someid');
You're not executing your factory so NGL.SceneBuilder is a function, not an object having the run property. Call the function :
NGL.SceneBuilder = (function() {
...
})(); // <<===
Note also that you forget to declare the element_id parameter in buildScene but maybe is it just for the question.

How do I call a nested JavaScript function properly

I'm trying to set up function a nested function that I can call throughout my script, but I keep getting "error undefined is not a function". Perhaps someone can help me with how to do this correctly.
First I set global my variables:
var trigger = document.getElementById('trigger');
var subject = document.getElementById('subject');
Then I create a show/hide function:
var toggleVis = function() {
function showSomething() {
trigger.classList.add("active");
subject.classList.add("active");
}
function hideSomething() {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
}
Then I set my event listener:
trigger.addEventListener('click', function() {
if ( subject.classList.contains("active") ) {
toggleVis.hideSomething();
}
else {
togglePicker.showPicker();
}
});
The reason I'm trying to do it this way is that there will be other triggers for subject on the page that will need access to the show/hide functions.
You can't access the functions inside the function, they are out of scope, you could attach them as properties to the wrapping function, but it looks like you just need an object
var toggleVis = {
showSomething: function() {
trigger.classList.add("active");
subject.classList.add("active");
},
hideSomething: function() {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
}
Your togleVis variable is a function and not an object so you can't do toggleVis.hideSomething(). Try updating your code to :
var toggleVis = (function() {
return {
showSomething : function () {
trigger.classList.add("active");
subject.classList.add("active");
},
hideSomething : function () {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
};
}());
With this toggleVis is now an object with two properties showSomething and hideSomething functions.

Categories

Resources