The Wrong Way to Ajax

| | Comments (1) | TrackBacks (0)

Recently I logged onto LinkedIn, to belatedly answer to connection requests.

LinkedIn now has some fancy ajax stuff, so you can just click accept on an invitation, and instead of loading a page, it does a background request and, if all goes well, that invite just disappears with a success message, leaving you to deal with the next request without leaving the page.

That's great. I did a lot of that when doing web application work for DAZ3D. One of the hallmarks of efficient e-commerce is giving people tools to get things done faster - and that meant things like list filters, type-ahead searches, ajax'd add-to-cart buttons - you name it.

But LinkedIn has an issue. See the screenshot:

I've used Firebug to peek at what is happening when it makes the request. As you can see, there's an error. The first time, I wrote it off as something transient, but I came back days later and got the same error.

I decided to log off and log back on, and the issue was fixed. Clearly, the "remember me" was sufficient for a normal page view, but not sufficient for accepting a connection request.

The problem arises because the ajax request is getting a normal full pageview back with the 500 error. I've written before about detecting ajax; if you're going to send a request over ajax, then whatever is handling the request should be aware, even if it's an error. There's nothing wrong with a 500 code for an ajax request that errors out; but your javascript should be ready to handle it.

In this case, as you can see from the (slightly privacy-screened) screenshot, I had a "spinny" (that's the technical term) that was going to sit there forever. That's especially bad, as a normal user will have no idea if the request has failed or is taking a really long time. Ideally, you throw a good error to the user; or, in this case, since you're not accepting their stale credentials, even redirect them to a login box. What you don't do is just throw a 500 error the javascript can't interpret and then stop there.

I personally like returning JSON objects, and I prefer to return them regardless of the code: 200 or 500, you get JSON if you made an ajax request. Then, my javascript always "fails over" - it looks for success. If there's no success message, it's an error.


$.get(href, function (data, textStatus) { var res = handleJSON(data); if (res['success']||false) { tgt.after(""+(res['success']||'Subscription added.')+""); $("#subsvcmsg").attr("id", "").fadeOut(2500, function() { $(this).remove(); }); } else { tgt.after(""+(res['error']||'An unknown error occurred trying to modify that subscription')+""); $("#subsvcmsg").attr("id", "").fadeOut(2500, function() { $(this).remove(); }); } } );

As you can see here, this code tests for a success message - using javascript's || operator to avoid any error messages being thrown to the user even if that element doesn't exist - and unless a success message is available, it prints an error. It tries to use the error returned by the server, if one exists - but again, if the error isn't there, it has a default message.

The point here is: don't leave your users hanging. (Also, you may not want to tell people your crack team is springing into action to handle a 500 error if that's not the case and it will still be failing days later, but that's aside from the point.)

I have long told fellow developers that trying to stick to tables that have entirely fixed width columns is good practice.

This tends to lead to, at the least, normalizing out text on a performance sensitive table/application.

Instead of:

CREATE TABLE foo ( idx int(10) unsigned not null auto_increment primary key, productId int(10) unsigned not null, price decimal(7,2) not null, description text not null default '', KEY productId_idx(productId) );

It might be broken up into:

CREATE TABLE foo ( myInt int(10) unsigned not null auto_increment primary key, productId int(10) unsigned not null, price decimal(7,2) not null, KEY productId_idx(productId) ); CREATE TABLE foo_text ( foo int(10) unsigned not null primary key, text not null default '' );

The idea is that if you're doing most operations with the "foo" table, you'll get much better performance without a variable width column (varchar, text, etc).

They used a table with a varchar(1) column, and got a massive performance hit, but only when the number of columns was large. I'd like to experiment to see if it is the number or pure width of the columns. (In short, compare something like 99xchar(3)+1 varchar(1), or 1xchar(297) + 1 varchar(1).

If you spend a lot of time dealing with languages that are loosely typed and have scalars running wild, then like me, you may be prone to doing something like this:

mysql> select NOW(); select GREATEST(NOW(), DATE_ADD(NOW(),INTERVAL 1 DAY)); +---------------------+ | NOW() | +---------------------+ | 2009-04-28 14:17:36 | +---------------------+ 1 row in set (0.00 sec)

| 2009-04-29 14:17:36 |
1 row in set (0.00 sec)

mysql> select GREATEST(NULL, NOW());
| NULL |
1 row in set (0.00 sec)

I'm glad the bug this caused had a minor impact, and this will hopefully be sufficient to slap me out of my loosely typed comfort zone for a while.


| | Comments (0) | TrackBacks (0)

This may be worth following.

I was pleased and amused at news that Seinfeld will apparently pimp Vista, which has been ravaged by issues such as poor performance, the way UAC trains users to click yes without providing real security, to say nothing of how Vista has horrible DRM, which distrusts the user and hurts consumers.

Vista is so bad, Microsoft came up with this elaborate plan to trick people into saying nice things about Vista. It might be easy to trick a few novice users into thinking Vista looks neat when they're in a lab, but do they know about the performance issues it may have on their hardware, or the frustrating DRM? For that matter, can they navigate the small ocean of different Vista licenses to select the right one? Vista is not what you'd expect from a half-decade of development. When you spend billions upon billions of dollars on a new operating system, you'd expect more than a "Defective By Design" piece of junk.

All this leads me to conclude that Seinfeld is the perfect spokesperson for Vista. Because Vista is a joke. Windows is the Smelly Car of personal computing. It makes computers stink, and Vista is just the latest horrible manifestation.

Seriously Wired, what's wrong with you?

The E71 looks more like a Blackberry Killer, but don't be fooled: This great white hope gives the iPhone a run for its money in a lot of different areas (yes, really).

No, not really.

  • Big, nasty keyboard
  • Display not as large as ipod, let alone iphone
  • MicroSD, but only 8GB.
  • $500 unlocked. Ouch. You're not iPhone 3.0, you know.
  • No headphone jack.

So it's an iPhone killer because... uh... the battery lasts 3 days! Yeah... because you can't do anything cool with it.


| | Comments (0) | TrackBacks (0)

I'm aware I haven't posted much. That said, I'm hoping to have an app I've been working on for the GAE (Google App Engine) done shortly, and will post some impressions about the GAE, and Python. (Wait, do I need a new category?)

After that, now that Apple has opened the developer floodgates, it's time to put in some time with my Cocoa for MacOSX book, iphone dev docs, etc, and do some iphone work. I enjoy my own iphone way too much to not develop something for it. Yay open platform! I did a small app for PalmOS ages ago, never even distributed it, but just had to to do it because I loved my palm and there was a decent gcc-based toolchain.

I am planning to upgrade to 3g, despite battery concerns. If necessary, I will disable the 3g except when I expect to be using lots of data. I never had an issue with call quality, and don't talk enough (<100m a month on average) to care. Maybe I can figure out a way to make that hotkeyed in some way. (I'd like to have a handful of settings toggles available when you double-click home when locked, like the ipod controls)

I grabbed a mybat external battery for the iphone. We'll see how that works, but tucked in my laptop bag, hopefully that will be serviceable in the clutch when battery is low and a recharge opportunity is not coming.

May 2012

Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Creative Commons License
This weblog is licensed under a Creative Commons License.