jQuery.when – Sometimes it’s the little things

Yeah, so today, I’m pulling down boatloads of JSON in this application I’m working on (mainly lookup-data-ish-data), and obviously if I’m going to use some of that data to do lookups, I need to wait until they’re all downloaded.  So, instead of some cheese eventing hack, I took advantage of the the little gem known as jQuery.when

(fyi, sorry for the crappy code-formatting below.  some day, i hope to take 15 minutes to figure out why either Live Writer or this crappy “Code” plugin suck so bad).

So, once my little lookup playloads were down, I was able to use it, nice-and-clean.  So, here’s where I slam down 4 ajax calls:

var ajaxSmackDown= function () {
     var promises = [];
     promises.push(detailsUtility.ajax(first ajax call here);
     promises.push(detailsUtility.ajax(first ajax call here);     
     promises.push(detailsUtility.ajax(first ajax call here);     
// (call as many as you want here…) return promises;
};

and here, we wait *when* to do our other stuff until they’re all done:

var promises = ajaxSmackDown();
$.when.apply($, promises).then(function () {
     // Do what you needed to wait on here
, function (e) {
     global.exceptionHandler(e);
});

Generic Cache helper for your asp.net MVC project

Scenario

ok, so everyone caches crap in one way or another, right (in fact, how many times have you written one of these little cheeseball cachehelpers in your career by now?).   Well, this is probably my hundredth, but maybe someone will find this one helpful.  This simple cachehelper is designed to encapsulate cached global items as well as session-based items (encapsulating, thus allowing any technique to be used internally).  In this implementation, global caching uses simple static-caching techniques, while the session makes use of…well…the session.  Easy to change later as scenarios permit.

The API is meant to be simple, and to minimize forcing the developer to work with thread-locking crap too.  So, in the case of global cache items, the developer, checks to see if an item is cached, while providing a Func<T> setter to call if the item is *not* cached, thus removing the need for revealing locking and such.  The session based one just requires an object of type HttpContextBase.

Here it is:

    {
        T EnsureGlobalItem<T>(Type key, Func<object> setter);
        T EnsureSessionItem<T>(HttpContextBase context, 
               Type key, Func<object> setter);
        void InvalidateSessionItem(HttpContextBase context, Type key);
     }

In our case, we inject this into our consumers, which tend to be asp.net MVC controller

public class StandardCacheHelper : ICacheHelper
    {
        private static IDictionary<Type, object> _cache;
        private static object _lock = new object();

        static StandardCacheHelper()
        {
            _cache = new Dictionary<Type, object>();
        }

        public T EnsureGlobalItem<T>(Type key, Func<object> setter)
        {
            lock (_lock)
            {
                if (_cache.ContainsKey(key) == false)
                {
                    _cache.Add(key, setter());
                }
                return (T)_cache[key];
            }
        }           

        public T EnsureSessionItem<T>(HttpContextBase context, 
            Type key, Func<object> setter)
        {
            VerifyParam(context, "context");
            VerifyParam(key, "key");

            lock (context.Session.SyncRoot)
            {
                if (context.Session[key.FullName] == null)
                {
                    context.Session.Add(key.FullName, setter());
                }
                return (T)context.Session[key.FullName];
            }           
        }

        public void InvalidateSessionItem(HttpContextBase context, Type key)
        {
            VerifyParam(context, "context");
            VerifyParam(key, "key");

            context.Session.Remove(key.FullName);
        }

        private void VerifyParam(object param, string paramName)
        {
            if (param == null)
            {
                throw new ArgumentException(string.Format("{0} must not be null.", paramName));
            }
        }
    }

s via Ninject:

public class UtilityModule : NinjectModule
{
public override void Load()
{
this.Bind<ICacheHelper>().To<StandardCacheHelper>().InSingletonScope();
}
}

The base controller exposes the helper as such:

    public class BaseController:Controller
    {
        private ICacheHelper _cacheHelper = null;

        public BaseController(ICacheHelper cacheHelper)
        {
            this._cacheHelper = cacheHelper;
        }

        public ICacheHelper CacheHelper
        {
            get{return this._cacheHelper;}
        }
    }

And then finally, the consumption is clean and simple (and testable of course!):

public class Foo{
     public string Name{get;set;}
}

private IEnumerable<Foo> GetFoos()
{
     Func<object> setter = () =>
      {
           return this.myService.GetFoos();          
      };
      return this.CacheHelper.EnsureSessionItem<IEnumerable<Foo>>(
this.HttpContext, typeof(IEnumerable<Foo>), setter)
}

Enjoy.  I’m coding my face off these days (love it!), so I’ll be posting lots more.  I’ve got a bunch of handy custom knockout bindings, some nice clean javascript modules to use (using the javascript module pattern), extensions to Javascript and many more helpful things.