• tweaking HTTP header to imporve performance

    Lately, I am doing some client side optimization. One of the techniques is cache. When browser firstly request a resource and get the response, the cache subsystem of the browser need to determine whether to cache resource. It is based on the response header Cache-Control, and Expires. When neither of them exists in the response header, browsers use their own strategy to cache, these strategies vary from browser to browser, so they are not predictable, we should explicitly set these headers. To explicitly disable cache in browser, we can use the following

    Pragma: no-cache 
    or
    Cache-Control: no-cache 
    or
    Cache-Control: no-store
    

    The Pragma: no-cache header is included in HTTP 1.1 for backward compatibility with HTTP 1.0+. It is technically valid and defined only for HTTP requests; however, it is widely used as an extension header for both HTTP 1.0 and 1.1 requests and responses. HTTP 1.1 applications should use Cache-Control: no-cache, except when dealing with HTTP 1.0 applications, which understand only Pragma: no-cache. According RFC 2616, Cache-Control: no-cahce is semantically different from Cache-Control: no-store. non-cache still allows browser cache a response, and the cache needs to re-validate the response with the origin server before serving it. no-store request browser not to cache response at all. However most browser treat "no-cache" as "no-store".
    To implement the semantics of "no-cache", we should use Cache-Control: max-age=0 or Cache-Control: s-maxage=0 or Cache-Control: must-revalidate.

    To explicitly to cache resource, we should use the following.

    Cache-Control: max-age=3600
    Cache-Control: s-maxage=3600
    //or
    Expires: Fri, 05 Jul 2002, 05:00:00 GMT
    

    The Cache-Control: max-age header indicates the number of seconds since it came from the server for which a document can be considered fresh. There is also an s-maxage header (note the absence of a hyphen in "maxage") that acts like max-age but applies only to shared (public) caches. The deprecated Expires header specifies an actual expiration date instead of a time in seconds. The HTTP designers later decided that, because many servers have unsynchronized or incorrect clocks, it would be better to represent expiration in elapsed seconds, rather than absolute time. An analogous freshness lifetime can be calculated by computing the number of seconds difference between the expires value and the date value.

    If browser hit the same url again, browser will firstly ask the cache sub-system to get a cache copy. If the cache is still fresh based on "Cache-Control" or "Expires" header, the cache is returned, and no request is sent to server. If the cache expired, determined whether a validator was send from the previous response, different request will be sent. If a validator of previous response is "Last-Modified", the following will apply.

    //validator of previous response
    Last-Modified: Sun, 03 Apr 2011 14:34:43 GMT
    
    
  • A enhanced curry method

    JavaScript is a functional language, it supports function composition, we can do curry with JavaScript. Douglas Crockford has defined "curry" method in his book JavaScript: The Good Parts to facilitate the steps to define curried function.

    Function.prototype.method = function ( name, func ) {
     if ( !this.prototype[name] ) {
      this.prototype[name] = func;
     }
    };
    
    
  • the when method

    In jQuery 1.5, there is a "when" method.

    function when(objects) {}
    
    
  • the promise object

    The jQuery.Deferred object has a function .promise(), it returns a promise object. Some other people call it future. In the async framework of .net, it is called Task<T> . It an object that promise to deliver a value in the future. So if believe that promise, you can express your believing like this


    promise.done(function () {
      var valuesOfFuture = [].slice.call(arguments, 0);
       alert();
    });
    


    The promise object does not has method of "resolve" and "reject". Because these method belong to server side. This pattern is very popular, but jQuery stream line this pattern. It is very useful pattern.

  • jQuery.Deferred Object

    Internally, the Deferred object is implemented with two _deferred object. The Deferred object offer two set of functions, done/resolveWtih/resolve/isResolved and fail/rejectWith/reject/isRejected. The are basically the functions of two internal _deferred object. The failed set function is the done/resolveWith/resoved/isREsolved function of fail object. But we don't have cancel function, because it is unnecessary, it is replaced with reject function. The done function will empty the failed list, and the reject function will empty the done list.


    It also introduced two new functions, then and promise. The then function is short cut to push a done function and failed function at one shot. We care about the success and compensation at the same time, we should consistently use then function instead of interweaving done or fail method. But if we don't care about that, we can interweave done and fail method. However, I think the then method should always be used, as it adds very little cost.


    Another new method is promise method. It basically return a new object or decorate an existing object with "promise prospect" or promise methods then, done, fail, isResolved, isRejected, promise. The promise object does the same thing as Deferred object, except it can not resolve, reject, which should be used at the server side. When we first call the d.promise(obj) with a real obj, then the obj is augmented with the promise methods and cached internally, and this pattern should be used at the first time. The subsequent call d.promise() will return the cached object.


    The constructor Deferred(initialize) can be passed with an initialize function. Your function can be defined as


    function (deferred) {
      //this == deferred
       this.then(x, y);
       this.m1 = "m1";
    }