Tech Is Hard

Credibility = Talent x Years of experience + Proven hardcore accomplishment

Tag Archives: jQuery

Making Mongoose Keep Its Promises on the Server


So far I really like the deferred/promise model. On the client it lets me get data as early as I want to, but defer using the response until it’s convenient; maybe not until inside some event handler. I can also place a call to .fail() for any promise in a convenient place, even before I make a call for data. The Deferred object coordinates calling any registered fail function(s) if anything errors — that’s right, you can specify multiple handlers for the failure — and all the done, then and always functions that have been registered, when appropriate.

To do the same thing on the server, I found jQuery Deffered for nodejs. After requiring it

var Deferred = require( "JQDeferred" );

and with a little function in my application

function promise (query) {
  var dfd = Deferred ();

  query .run (function (err, doc) {
    if (doc) {
      if (doc.length > 0 || Object.keys(doc).length > 0) {
        console .log ("found\n", util .inspect(query));
        dfd .resolve (doc);
      }
      else {
        console .log ("not found or no rows\n", util .inspect(query)); 
        dfd .resolve (null);
      }
    }
    else {
      console .log ("error or no data object\n", util .inspect(query));
      dfd.reject (err ? err : null);
    }
  });
  return dfd .promise ();
}

Works for any Mongoose method that returns a query, like find, findOne. It’ll need to change to fold in the rest of my calls. In one function, I need to get 3 rows to verify something before I take action. Using jQuery Deferred and this promise function, dealing with 3 asynchronous calls with very little code looks like

var CloseAll = function (query, resp) {

  Deferred .when (
    promise (modelA .findOne ({modelAkey:query.body.A})), 
    promise (modelB .findOne ({modelBkey:query.body.B})), 
    promise (modelC .findOne ({modelCkey:query.body.C}))) 
    .fail (function (err)    { resp .send (_.extend (query.body, err), 500); })
    .done (function (dataA, dataB, dataC) {
          now do stuff that require all 3 things

Pretty sweet.

Promises, promises. A concise pattern for getting and showing my JSON array with jQuery and Underscore


I’m forgetting the async/sync stuff from before in favor of thenables. Deferred and its more polite personality, promise. There are just certain things that I think would be really tough to do with a callback architecture.

Normally, if I were showing a view of something I wouldn’t $.get() it from the server until my DOM is loaded, because I can’t do anything with the response until I’ve got elements to manipulate. But with jQuery’s implementation of AJAX calls, which return a promise, I can set it up so that I get data as soon as the Javascript is loaded and guarantee that I don’t try to move the data to DOM elements until it’s ready, too.

var mydata = $.get (window.location.origin + ":8080/foobar");

$( function () {
  mydata .done (showdata);
});

function showdata (data) {
  $( 'ul#something') .html (
      _.map (data, function (row) {
           return '<li>' +row.name +'</li>';
      }) .join ( '' ) );
}

If data looked like [{“name”:”john”},{“name”:”bob”},{“name”:”fred”},{“name”:”alice”}], then our <ul> now looks like

<ul id="something"><li>john</li><li>bob</li><li>fred</li><li>alice</li></ul>

I think that’s slick. showdata won’t get called until the DOM’s loaded and we have the data, but there’s no waiting before we ask for it from the server. We use map() to output an array of HTML strings (instead of concatenating), then join those and put the output into $(‘ul#something’). There’s only one variable used — which is a very good thing, BTW, lots of variables is a code smell, IMO.

Another nice pattern I use:

Imagine this jQuery GET for some set of choices within a “topic”

var topic_data = $.get (
  window.location.origin + ':8080' + '/topic/' + some_criteria);
{"name":"foobar","choices":["bob","fred","alice"]}

And separate documents for a user’s choice for that topic, which are referenced by the “name” of the topic.  In other words, I had to get that topic to find the key to use for the next GET.  I need to render the topic_data in showTopicChoices regardless of what happens in that GET.

topic_data .done (showTopicChoices, function (topic) {
  $.get (window.location.origin + ':8080' + '/user/topic/' + topic.name) 
    .done (overlayUserChoice);
 });

It’s a nice way to separate the rendering of more general data from other indicators.

Powerful jQuery Shorthand to Move Data Into DOM


I realize this is basic, though not obvious, jQuery stuff, but it’s powerful in the amount of work that can be done.  One could devise a fairly elaborate convention to make rendering driven largely by the markup.  Assume some JSON object like

var myJson = { "name": "Grant", "age": "ancient", "position": "seated" };

and elements like

 
<p myns:field="name"></p>
<p myns:field="age"></p>
<p myns:field="position"></p>

With this jQuery call I can set the text of all the elements without any knowledge of the model’s contents.

    $('[myns\\:field]') .text(function(idx, txt) {
      return myJson [$(this) .attr ('myns:field')];
    });

There’s a lot of potential; I’ll have to see if it’s worth it under varied scenarios.