Referring to external function parameter within $timeout - javascript

I am listening to websocket events with SockJS and want to insert received objects into my $scope.mails.items which is an array. I have the below code snippet and my problem is that for some reason I am not able to pass the message into my delayed function. I know... I tried to read some explanations about this issue asked repeatedly, but still was not able to figure out why it is not working in this particular case. The reason I need to delay this is that I'd like to make sure it gets applied to my view, it does not otherwise.
MyService.receive().then(null, null, function(message) {
$timeout(function(m) {
if($scope.mails.items.indexOf(m) == -1) {
$scope.mails.items.push(m);
}
}, 0, true, message);
});
When debugging it, I can see that the message variable has proper value but when it comes to stopping in the middle of my delayed function, m is not getting the data, however I would expect $timeout to pass it down.
Can you please help?

Not sure why m is not getting value (explanation welcome), but this works:
MyService.receive().then(null, null, function(message) {
$timeout(function() {
if($scope.mails.items.indexOf(message) == -1) {
$scope.mails.items.push(message);
}
}, 0, true, message);
});

The callback function for $timeout does not take any parameters. That m parameter is always going to be null, just use the message parameter from the outer function.

Related

Why the variable value from is not accessible in following code snippet?

I've following Javascript code snippet :
authData=ref.getAuth();
if(authData == null){
//TODO find an elegant way to manage authorization
// window.location = "../index.html";
} else {
ref.child("users").child(authData.uid).on("value", function(snapshot){
$( "span.user-name").html(snapshot.val().displayName);
loggedInUser.displayName = snapshot.val().displayName;
//alert("Name inside : "+loggedInUser.displayName);
//Here it displays the value
});
}
alert("Nameada is out : "+loggedInUser.displayName);
//Here it shows 'undefined'
why?
I want to use the variable value loggedInUser.displayName where did I shown alert.
Can someone please help me in accessing the value and displaying the alert?
Thanks.
Your final alert is executed when the callback function (function(snapshot){ ... }) has not yet been called. Note that the callback function is called asynchronously, so it only gets executed after the currently running code has completed and the value event is triggered.
This also explains why the inner (commented out) alert does work. Just realise that this piece of code (the call back function) is executed later than the other alert, even though it occurs earlier in your code.
You could "solve" it by calling another function from within the call back, like this:
authData=ref.getAuth();
if(authData == null){
//TODO find an elegant way to manage authorization
// window.location = "../index.html";
} else {
ref.child("users").child(authData.uid).on("value", function(snapshot){
$( "span.user-name").html(snapshot.val().displayName);
loggedInUser.displayName = snapshot.val().displayName;
whenUserLogged();
});
}
function whenUserLogged() {
alert("Name : "+loggedInUser.displayName);
// anything else you want to do....
}
Some suggestions for improvement
Don't use too many global variables (in your code all of them are global), and instead pass variables as function arguments.
You may want to look into promises.

Javascript Element Validation within If-Statement

I'm having issues when adding an element validation within an if-statement.
Basically, irrelevant of the result of the if-statement, Protractor is still trying to find the element specified within the if-statement.
Here is the code that is still running even though the if-statement returned false:
if (thisIsAlwaysFalse == true) {
console.log(':::::::::::::::' + thisIsAlwaysFalse);
it('If-statement test', function(done) {
var elementToFind = element(by.xpath('//td[contains(#class,"hello")]'));
browser.wait(function() {
return browser.isElementPresent(elementToFind);
}, 5000);
elementToFind.click();
done();
});
}
Also, funny thing is that the console.log part is successfully ignored!
Anyone has a solution for this or possibly knows why this is happening?
Thanks in advance :)
Have you debugged the problematic area?
Nevertheless, your always-false statement is probably a promise, which is always a truthy value. In order to solve it, you need to put the whole block to then callback.
For example:
doStuff()
.then(function (result) {
if (yourAlwatsFalsyCondition(result) {
return elementFindYouDid(results)
.moreStuff(doMore);
}
})

Passing value into function and variable scope in JQuery

Link to code example:
http://jsfiddle.net/99Shr/
This code works for a given click handler, and $(this) takes on the particular class.
I am attempting to take the code that is inside the click function and put it into it's own function. The reason I want to do this is because I would like to replace quantity-- with quantity++ depending on which click handler is called. The issue I am running into is that the variables when called in the function are undefined since $(this) is window.
I am well aware that I may be doing this wrong to achieve what I want and am open to learning a better way to achieve it.
function price(change) {
return change;
}
$('.cart-item-decrease').click(function(){
price('quantity--');
});
or
$('.cart-item-increase').click(function(){
price('quantity++');
});
You can customise the event handler registration so that additional data gets sent to your function:
function myClickHandler(e)
{
// ...
quantity += e.data.increment;
// ...
}
$('.cart-item-increase').on('click', null, {
increment: 1
}, myClickHandler);
$('.cart-item-decrease').on('click', null, {
increment: -1
}, myClickHandler);
Here, the increment property gets sent to myClickHandler as e.data.increment.

backbone.js model.save doesn't set the id

I've inherited a backbone js based app. I really like backbone and i'm just starting to get my head around it. From my understanding when model.save is called on a new entity it should post that to the server, the server should return the same json but with an id alloted and backbone should persist that id to the model so that further saves result in a PUT with the ID for update.
However, when I call model.save() and then try to get the model.id property, it's null.
Is this because I'm not doing it with a call back? So the property hasn't been set yet?
How would I set the success callback? calling model.save({success: function(){...}})doesn't work?
here is the actual call:
model.save(null, {
success: function () {
alert('success');
},
error: function () {
alert('error');
}
});
Something feels odd about this. Setting silent: true only makes it so none of the events get fired. Everything else should happen normally. In other words, don't assume that setting slient: true is the right answer here...
I suspect you are actually throwing an exception some place (probably with validation or something like that) and somehow, setting silent: true is causing everything to flow through.
I would strongly suggest that you remove this option and check your console or run with the debugger... I suspect you have a bug lurking around there some place.
Some suggestions: Take a look at the annotated source for the model.set function. It gets called before your success callback will get called. Inside of that function, there are several things that will happen if silent is false. These include validation, individual property change triggers, and a global change trigger. I would bet money that either the validation is failing or something that is listening to the changes is throwing an exception.
i needed to set the silent: true on the save:
model.save(null, {
silent: true,
success: function () {
alert('success');
},
error: function () {
alert('error');
}
});
I had the same issue, turned out to be because my custom parse was failing

How to set status with HTML5 Web Database api

I'm using the HTML5 Web Database API and I have a function that checks to see if the app needs to go and perform it's setup phase :
this.setupRequired = function() {
var status;
try {
this.db.transaction(function(tx) {
tx.executeSql("SELECT * FROM settings", [], function (tx,result) {
if (result.rows.length == 0) {
status = true;
} else {
status = false;
}
}, function(tx) {
status = true;
})
});
} catch (e) {
return true;
}
return status
}
I'd like to return true or false based on whether there is data in the settings table or not (or if the settings table doesn't exist). The status var isn't getting set, I'm guessing this is due to scope issues and the anonymous callback functions. I'm pretty sure I need to use a closure here to correct the issue but can't quite get it right.
I'd like to return true or false based on whether there is data in the settings table or not
You can't. It is not known whether there is data in the settings table at the time the setupRequired() method has to return. This will only be known when the SQL database has performed the query and invoked the callback function. That happens only after setupRequired() and the functions that led to it being called have all exited, returning control to the browser.
That's the whole point of the callback function being passed to executeSql(). The function is not executed right away, so status will not have been touched by the time return status is reached. What's more, any exceptions that occur inside the callback functions will not cause the catch(e) block to be executed, because the try...catch block will long have been exited by the time the function that was defined inside it is actually called. So this try...catch is effectively useless.
This is ‘asynchronous’ coding. Just because some code is below a function, doesn't mean the function's going to execute first.
You could probably set status as a property of the object or another object of your own making.
You could also check at each stage what 'this' is or what value status has using firebug.
Hmm, I don't have any experience using this API but it appears that you are trying to set a value in a callback function and then return that value from the outer function. Assuming the callback is asynchronous, this will not work. I think your best bet is to change your code to something like:
this.setupRequired = function() {
try {
this.db.transaction(function(tx) {
tx.executeSql("SELECT * FROM settings", [], function (tx,result) {
if (result.rows.length == 0) {
doYourSetupFunction();
} else {
//don't;
}
}, function(tx) {
doYourSetupFunction();
})
});
} catch (e) {
doYourSetupFunction();
}
}
So that the setupRequired function is reponsible for checking and triggering the setup.

Categories