Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
Had a fun time today trying to find the bug in my code until I finally distilled the problem down to the following abstraction:
code:
<html>
<script language="javascript">

window.onload=init;

var dependents = new Object();
dependents['apples'] = "apple";
dependents['oranges'] = "orange";

function init()
{
	for( key in dependents )
	{
		document.getElementById(key).onchange=function(){alert(dependents[key])};	
	}
		
}
</script>
<form action=GET>
<select name="apples" id="apples" title='' tabindex="0"  >
<option label="granny_smith" value="granny_smith">granny smith</option>
<option label="golden_delicious" value="golden_delicious">golden delicious</option>
</select>
<select name="oranges" id="oranges" title='' tabindex="0"  >
<option label="navel" value="navel">navel</option>
<option label="mandarin" value="B">mandarin</option>
</select>

</form>

</html>
Please excuse the crappy nature of the example, but if you run this you'll see two select boxes, one with apple types and one with orange types. When you change the value of a select it's onchange will trigger an alert. Now one might think each select box would pop up with the respective apple/orange alert. That's not what happens. What happens is each select box (or every select box, if we added more inputs in the same nature) will have it's onchange set with 'key' bound to whatever value it was on the final iteration of the loop. It looks a new onchange is applied when we leave scope (not all scopes, nesting it in an if block won't work, for instance). Now, modify the js like so:
code:
function init()
{
	for( key in dependents )
	{
	    setOnChange(document.getElementById(key), key);
	}
		
}

function setOnChange(element, key)
{
   element.onchange=function(){alert(dependents[key])};	

}
...and each pulldown will now alert the value of key at the time that element was selected in the loop.

I couldn't find this documented anywhere as intended or a bug or anything like that. Am I crazy in thinking this should be a bug/misfeature?

Adbot
ADBOT LOVES YOU

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
Edit: forgot it's href's onclick, so just return the confirm like ^^^^^

code:
function myOnClick()
{
  var answer = confirm('We are not responsible....');

  if( answer ) // they clicked OK
  {
    window.location = myHref;
  }

}

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
Before accepting it serverside you would still need to validate that the key from the client fits the constraints of userid/sessionid or whatever, on top of the normal sanitizing & escaping, otherwise it'll be a vector for shenanigans. But yes if you're going to have clients creating unique PKs then definitely come up with a seeding process for all ids that it's tied not only to the logged in user but the session/frontend instance that is running, and have some way to re-validate serverside.

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD

DreadCthulhu posted:

Backbone question: do I actually ever need to remove events bound to children of a view if I delete the entire view each time I navigate to a different one? I keep reading that modern browsers do a good job at automatic recollection of dangling event handlers. Is that not really the case?
I don't know that to be the case with browsers, but there are a number of conventions to help manage it in backbone. This post is a pretty good jumping off point:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
I'm confused. Is this username/password specific to person A and B or is it a standard one for the company?

If the login (whether it's one per user or a universal one) is so important I think javascript might not be the way to go because if they're on Computer 1 and the JS is running on Computer 1, someone clever/malicious enough will probably be able to extract it. This depends on what's at stake about the site being accessed outside of the company. Is it meaningless red tape that came out of policy (ie. managing the whole "kicking other users off" thing) but nothing is really too vulnerable and training/guidance/trust would be enough, or does it really offer a black eye for the company that escalates it to Not Even Once levels of security? If it's the former where the people can be controlled to some degree, depending on their trustworthiness, you can just provide some policy ranging anywhere from communicating "hey these logins have to be used here only so just use this widget and never log in from anywhere else" all the way to "if you're ever caught trying to obtain or otherwise misuse this login you'll be fired/expelled/beheaded please sign here to acknowledge" (though if it needs to be that extreme you might as well treat it as the latter). If it's in the Not Even Once category you might want to take the login stuff out of javascript completely and come up with a way that will prevent them from ever having access to the password, ie. someone can pick apart javascript or hidden form elements and so on but won't get anywhere. There's a wide number of ways to do that, some of the better ones depend on whether you can work directly with whoever runs that site.

E:F,B

Bhaal fucked around with this message at 23:48 on Apr 3, 2013

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
That works for getting the gist of race conditions and stuff for the truly uninitiated, but to me the largest hurdle for people (esp. in a js context) isn't understanding that concept but rather having the sensitivity to notice when something is async or not. To me that is what trips people up far more than getting how a callback or promise works. They can follow a contrived example and get it, but in practice they are just misidentifying many non-blocking call as blocking. Typically that boils down to just learning to be vigilant to the specifics of what a function call is going to do, and breaking it down to either i/o or in-memory-only (a coarse but generally applicable guideline for determining if something is blocking or not).

As for suggestions, if they get the fundamentals, maybe scour up some code snippets with some that correctly catch async behavior and some that do not (stackexchange should be rife with both) , and have them quiz themselves on being able to tell whether snippet B is correctly written or not, if not where is the race condition, how to fix, etc...

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
Most recently I've seen it with file i/o and gulp, specifically. Like doing some stream/pipe/dest chain and then assuming the output file will be there and ready for usage downstream in the main execution line of the gulp task or wherever. On a local build you may not notice the problem because you aren't minifying and taking extra steps that a production build would, so the files ends up being ready in time just by chance, and/or a version of it already existed on your local so you don't get errors.

Maybe what I mean is more that if you're a developer who isn't seasoned to think about async consequences all the time, and you're dealing with an async call that manipulates state in one area*, then it makes for an easy trap to forget/overlook that when trying to access the same piece of state in another area.

* Or worse, have those calls wrapped such that no callback or .then is required to use the wrapper, probably due to another unseasonsed developer who thought they were being tidy and helpful by "containing" the async call

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD

Knifegrab posted:

OK I will try to make up some assumptions about promises and the code I want to write, I will admit I am probably wrong.

- The standard PG library is blocking because the request function does not contain a callback in its paramaters, so since its not utilizing callbacks, its a sync function not async.
I'm not sure which library you're referring to. Do you have a link to it? I looked at a few node / pg libs and they all seemed to take a callback arg. If the one you're looking at doesn't, then it might have promises baked in and what it's returning is a promise, and is therefore non-blocking.

quote:

- Promises only work when used with async functions already.
Not really, and this might be a source of confusion. Promises can work on any function. You can take: function (a,b) { return a+b} or function () {return "hello!"} and wrap each of them into a promise.

The intention of a promise is to take your function, run it, and box up two things about it: (1) when it finishes and (2) what it returns. Then the promise object is attached to that metaphorical box and returned to the caller. The caller will then call things like .then which will attach further events of what to do with the your function's return value (and that's where the async part gets put in). When your function is ready (ie. that "box" has the when & what components of your function satisfied) the function in .then will be triggered to run. The fact that your a+b function will be ready immediately (because it already ran) is insignificant to the promise object. It still goes through all the motions and it just so happens that as soon as .then is ready it gets executed right away.

Now, when a function you call returns the actual value you're looking for, a promise can wrap it directly like with a+b above. However when your function requires a callback of its own, in order to behave the same way, the promise object needs to attach its own callback (a deferred object, which has its own internal promise which is what gets returned in the main thread of execution). From the promise object's perspective, it is saying "Look, your function doesn't directly return the value you're looking for and it does not signify that it is completed. Instead it is the _callback_ that gets passed to your function that we're interested in, so let's give it my own callback and I'll now use that as my trigger for when you function is both finished and has a return value that we're interested in". This of course ends up being the most typical use case because wrapping a+b is generally pretty silly (but it can be done, and might be a helpful exercise in demystifying what promises are actually doing).

quote:

- However I also am under the impression that promises are a good way to keep a system from being bogged down by blocking requests (such as a slow SQL request).
Not really, on two counts. First, using our a+b example, if we instead had some crazy nested loops of dummy addition that took forever to execute, it would be both blocking and take a long time, and the promise structure wouldn't be ready until it finishes anyway so our main thread of code would be blocking just as much (because we are executing the nested loops directly in the main thread). There are ways to wrangle something like that into an async process (and you could use promise structures to do so) but that's not really the intended usage of promises. Secondly, I doubt the pg library is blocking. DB interaction, file i/o, user input and network requests in general can all be assumed to be asynchronous in js.

quote:

I literally want to take a single file of code, connect to my database (a util file I already have) and just do one request to a table in postgres like this: "select * from config.chapters". But I want to do it in promises without using any extra extensions.

I guess I am just confused as to how to wrap something in a promise or how to start a promise off. I just hate promises.
code:
var pg = require ("my-pg-lib")
var q = require("q")

// example one: your pg lib returns a promise -- no q needed!
pg.query("select * from config.chapters")
	.then( function (rows) {
		console.log(rows) // we should see the data from config.chapters in the console
	})

// example two: your pg lib requires callbacks, so we'll invoke q to handle that poo poo and will assume it's the node callback convention
// Note: it is usually a practice to instead wrap these into a function and "return deferred.promise" instead.
var deferred = q.defer()
pg.query("select * from config.chapters", deferred.makeNodeResolver())
deferred.promise.then(function (rows){
		console.log (rows) // db data!
	)}

NOTE: I left out pretty much any discussion about error handlers and so on, just to make the explanations and examples simpler, but those are of course a necessity.

(EDIT: left some var declarations out, coffeescript is great but leads to bad habits)

Bhaal fucked around with this message at 20:00 on Aug 10, 2015

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD
Honestly they take a 70/30 mixture of practice and reading to really have it all sort of click. Most of my "ah-ha" moments came from discovering & tracking down race conditions that snuck up on me after I thought I had done everything correctly. But to get there you have to build something big enough with all the little app-specific complexities and so on that your code ends up being more than just a handful example snippets cribbed from the internet. But that way you at least will have some substantial code to tinker and troubleshoot with.

Adbot
ADBOT LOVES YOU

Bhaal
Jul 13, 2001
I ain't going down alone
Dr. Infant, MD

Knifegrab posted:

No I get that, but what I don't undertand is how writing:

[jsx]

Is so much better than writing:

[js]
In addition to what others are saying, it's also :airquote: better :airquote: because the former lets you read & construct in a medium that is much closer to the resulting artifact (ignoring all the spans thrown in). I use airquotes because readability arguments can turn into philosophical battles and "better" is kind of under-equipped as a form of comparison. That said I just recently wrapped up the 1.0 of a little self project using react and agree that it can be a very powerful tool and reading dev blogs didn't really make it all click for me. I'm averse to "Now you're thinking in ..." type slogans that just try to self promote their tech stack, but with React it sort of panned out that way for me where once I was comfortable enough with how they structure things it really seems quite sensible. Returning to backbone or whatever just feels like it's going to be clunky to me now. So I'm in the camp that feels it's better or at least a solid progressive step forward.

quote:

The term "variable interpolation" is one of those smart words that I am too dumb to understand. Is it similar to parameterizing a sql query to prevent injection?
Kind of, and it does come off as fancy language. Something like db.query("select * from users where id=?", user_id) would be a form of it. Interpolation ("between the poles") in this context just means that variables and everything else all fit inside of one string. There's no composition or glue or whatever else needed. "I've worked at $COMPANY since $HIRE_DATE." is just a single, atomic... thing, so therefore the variables have been interpolated into the thing. Versus eg. "I've worked at "+company [...] which is not interpolated. The interpolated string still needs to be cut up and other bits will get substituted around, yeah, but all of that is abstracted and contained so you don't have to do all of it yourself every time, which closes out a ton of opportunities for typos and bugs and so on eating up developer time. That's the central advantage of it, in a nutshell.

Bhaal fucked around with this message at 01:45 on Aug 18, 2015

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply