Two-time encapsulation of jquery Ajax and AJAX caching Agent components: Ajaxcache detailed _jquery

Source: Internet
Author: User
Tags closure http request instance method delete cache

Although the newer API for jquery is already very useful, but in the actual work or have to do two times the need for encapsulation, the benefits are: 1, two times after the encapsulation of the API more concise, more in line with the use of personal habits; 2, you can do some unified processing of AJAX operations, such as appending random numbers or other parameters. At the same time at work, we will find that there are some AJAX-requested data that is not high on real-time, even if we cache the first request, and then return the cached data directly when the same request is launched again without affecting the related functionality, through this manual caching control, Reduce the AJAX request, more or less can help us improve the performance of the Web page. This article introduces my own approach to these two issues, welcome to communicate and correct.

Click on the code to download (note: Because of the use of Ajax, it can not run under the file protocol, must run under HTTP)

1. Encapsulation of jquery Ajax

In fact, this part of the relevant content in a previous blog introduced, but it is only a reference, not detailed, and the AJAX cache proxy component implementation is based on this two-time package after the Ajax component, so it is necessary to explain it here in detail, Although the implementation is not complex (see note for more details):

Define (function (Require, exports, module) {var $ = require (' jquery '); Unify the creation of Ajax object function Create (_url, _method, _data, _async, _datatype) {//Add random number if (_url.indexof ('? ') to the key parameters. Gt
    -1) {_url = _url + ' &rnd= ' + math.random ();
    else {_url = _url + '? rnd= ' + math.random ();

    ///To add AJAX logo for the request, convenient background to distinguish Ajax and non-AJAX requests _url = ' &_ajax=1 ';
      Returns the Ajax object created by jquery so that you can add the callback via//.done. Fail always after you get the object externally (this is to preserve the useful part of the jquery Ajax return $.ajax ({
  URL: _url, DataType: _datatype, Async: _async, Method: _method, Data: _data});
  //ajax is the only instance of this component that is globally unique, and its instance method adds//methods objects to the parameters of each instance method of Ajax by following the Loop code://name: Method Name//method:http request method, Get or post
        Async: Asynchronous//datatype When sending request: returned data type, HTML or JSON var ajax = {}, methods = [{name: ' HTML ', Method: "Get", Async:true, DataType: ' HTML '}, {name: ' Get ', method: ' Get
',        Async:true, DataType: ' json '}, {name: ' Post ', Method: ' Post ', async
        : True, DataType: ' json '}, {name: ' Syncget ', method: ' Get ', Async:false, DataType: ' JSON '}, {name: ' Syncpost ', Method: ' Post ', Async:false, DA

  Tatype: ' JSON '}]; Because the two-time encapsulation needs to be provided externally with each instance method to create Ajax logic is the same//so the unified definition of each instance method/key code in this way for the function called immediately in the following code//It returns a new closure function as an instance method for (var i = 0 , L = methods.length; I < L;
         i++) {Ajax[methods[i].name] = (function (i) {return function () {/** * Each instance method receives three parameters * First indicates the address to be requested * The second represents the data to be submitted to the background, an object, such as {param1: ' value1 '} * The third represents the data type returned by the background, the most common is HTML or JSON, large
          In case this parameter does not need to pass, will use methods inside the definition datatype * * var _url = arguments[0], _data = arguments[1], _datatype = arguments[2] | |

        Methods[i].datatype; Return Create (_url, METhods[i].method, _data, Methods[i].async, _datatype);
  }) (i);
} return Ajax;

 });
The main thing this Ajax component does is:
1 Uniform supply of random number parameters and Ajax request identification;
2 The jquery API is packaged, and the method provided externally is clearer.

How to use:

Define (function (Require, exports, module) {var Ajax = require (' Mod/ajax '); Request HTML Content ajax.html (' Html/demo ', {param1: ' value1 ', param2: ' value2 '}) in Get mode. Done (function (response) {/

  /Request successful Callback}. Fail (function () {//request failed callback}). Always (function () {//request completed callback}); Request JSON Data Ajax.get (' Api/demo ', {param1: ' value1 ', param2: ' value2 '}) in Get mode. Done (function (response) {//please

  Callback for Success}. Fail (function () {//request failed callback}). Always (function () {//request completed callback}); Request JSON Data ajax.post (' Api/demo ', {param1: ' value1 ', param2: ' value2 '}) on post. Done (function (response) {/

  /Request successful Callback}. Fail (function () {//request failed callback}). Always (function () {//request completed callback}); Sends a sync request to get the JSON data ajax.syncget (' Api/demo ', {param1: ' value1 ', param2: ' value2 '}). Done (function (respons

  e) {//Request successful Callback}). Fail (function () {//request failed callback}). Always (function () {//request completed callback}); Sends a sync request post to get the JSON data ajax.syncpost (' Api/demo ',{param1: ' value1 ', param2: ' value2 '}).

Done (function (response) {//Request successful Callback}). Fail (function () {//request failed callback}). Always (function () {//request completed callback}); });

Because each instance method of this component returns objects that are created by $.ajax, we can use them as usual. Fail. Always to add a callback, just like the direct use of $.ajax without any distinction. Why is the API designed to be HTML, get, post, Syncget, Syncpost these methods, and even datatype are basically fixed?

That's because in the project, we can all agree that we can only use HTML or JSON when the asynchronous request datatype, other datatype not allowed, now the Web project these two ways are fully enough, At least I've never had a situation where I had to use other datatype, and in the actual work of HTML, GET, post, Syncget, Syncpost, these methods almost cover all the asynchronous requests we need, whenever we want to use Ajax, The only thing to consider is get or post, sync or asynchronous, ask for HTML or JSON three problems, through which they can solve each problem. Of course, the Jsonp,rest API in both cases said that this component is not for them, this is its limitations, it is still inclined to use in traditional Web projects.

2. Ajax Caching Agent

To implement a simple Ajax caching proxy component, the first step is to understand the role of the caching agent, which begins with the caching agent scenario: When a request is first initiated with a caching agent, the data is cached after the request succeeds, and then the cached data is returned directly when the same request is initiated again. The role of the caching agent is to control when the request is sent to the background to load data, and when not to send the request directly from the cache before reading the data loaded. To implement a simple caching agent, there are three issues to resolve:

1 The proxy object must have the same API as the object being represented
With the previous Ajax component, which provides HTML, get, post, Syncget, and Syncpost methods, its proxy objects must have these methods at the same time, and the invocation method, the incoming parameters must be exactly the same, so that when we use the proxy object, It's no different than using the original Component object. And in the cache proxy, in some cases, it is necessary to invoke the original Component object to send AJAX requests, if the interface is different, different calling mode, different parameters, how to ensure that the internal can correctly call the original component objects? Another advantage of this condition is that when we do not want to use the proxy object next time, we can replace the proxy object with the original component object at the lowest cost.
This is actually the basic requirement of Agent mode in design pattern.

2 cache indexing problem when caching data stores
In other words, what index can we use to ensure that the same requested data is cached, and the next time we find it, we can find it according to the request information? The AJAX cache differs from other caches in that the address it requests may contain variable parameter values. The same address if the following parameters are different, then the corresponding request results are not necessarily the same, so for simplicity, you can consider the request address and request parameters uniformly as a cache index, so that the cache can be simple management. At the same time consider other variability, there should be some other requirements, as described in the following component implementation of the annotation note.

3) Cache Valid time
Although the caching proxy to implement is simple, the problem must be considered, each cache proxy instance, the effective time to cache data is not necessarily the same, some may only cache a few minutes, some may cache for several 10 minutes, and when the cache time expires, the cache agent will have to delete the original cache, and then reload the data to the line.

To synthesize these questions, based on the first part of the Ajax component, the final implementation of the cache proxy component Ajaxcache code is as follows (with comments detailed):

Define (function (Require, exports, module) {var $ = require (' jquery ');

  var Ajax = require (' Mod/ajax ');

  Cache list var cache = {}; /** * Generate Cache Index: * Since the index is generated from the URL and data (data is an object, storing Ajax to be submitted to the background) * So if you want the same URL, the same data can effectively use the cache, * Do not include the URL and data in every Variable parameter values such as random numbers * For example, there is a request: * url:aaa/bbb/cccc?r=0.312738 * Data: {name: ' JSON '} * where the URL after the R is a random number, each time the external launch of this request, R The value will vary * because R is different each time, eventually, the cached index will be different and the result cache will not be hit * Note: Random numbers can be placed in the original AJAX components * and: if it is the same interface, preferably within the same page, the path type of the unified URL, or both relative path, to
  It's all an absolute path. * Otherwise, the cache cannot be effectively managed/function Generatecachekey (URL, data) {return URL + $.param (data); } return function (opts) {opts = opts | |

    {}; var cacheinterval = Opts.cacheinterval | |
    (1000 * 60 * 60);//cache valid time, default 60 minutes var proxy = {};
        for (var i in Ajax) {if (Object.prototype.hasOwnProperty.call (Ajax, I)) {//proxy to define AJAX components for each instance method on the proxy object Note that this immediately invoked function expression//It returns a closure function that is the final proxy method proxy[i] = (function (i) {returnfunction () {var _url = arguments[0], _data = arguments[1], CacheKey = Generateca

            Chekey (_url, _data), CacheItem = Cache[cachekey], iscachevalid = false;
              if (CacheItem) {var curtime = +new Date ();
                if (curtime-cacheitem.cachestarttime <= cacheinterval) {//If the interval between the request time and the cache start time is within the cache valid time range, it means that the cache is valid
              Iscachevalid = true;
              else {//otherwise clear the cache delete Cache[cachekey]; } if (Iscachevalid) {//Simulate an asynchronous task to return the cached data//The $defer delay object, you can ensure that this simulation is either 
              The object returned by the original Ajax component call has the same API//This is the key to the proxy: the proxy object should have the same API as the object being represented//only so that when we cancel the agent, we do not modify the component with the proxy var $defer = $.
              Deferred ();
              settimeout (function () {$defer. Resolve (Cacheitem.res);
              }, 10);
    Return $.when ($defer);        }//cache failure or no cache call the original AJAX component of the same method to request data back to the background ajax[i].apply (Ajax, arguments). Done (funct
                Ion (RES) {//cache the results after the request succeeds and record the current time as the start time for the cache Cache[cachekey] = {res:res,
          Cachestarttime: +new Date ()});
      }) (i);
  } return proxy;
};
 });

In the first part and in this part of the implementation, the most critical is the immediately called function expression, without it returned the closure, the code will have problems, which is the closure of the application in the cycle of the classic problem.

3. Demo Effect

To illustrate the effect of caching proxies, I did a demo:

One of the ajax.js is the first part of the implementation of the Ajaxcache.js is the second part of the implementation of the presentation page corresponding to the code in the html/demo.html, related JS is js/app/demo.js:

Define (function (Require, exports, module) {

  var ajaxcache = require (' Mod/ajaxcache ');

  Create proxy object
  var Ajax = new Ajaxcache ({
    cacheinterval:10 * 1000
  });

  var count = 5;

  Console.log (' Point-in-time: First ' + 0 + ' s, timer start!) ');
  var t = setinterval (function () {
    if (count = 0) {
      console.log (' point-in-time: First ' + (5-count + 1) * 4 + ' s, Timer end!) ');
      return Clearinterval (t);
    } else{
      console.log (' point-in-time: First ' + (5-count + 1) * 4 + ' s: ');
    }

    Ajax.get ('.. /api/data.json ', {
      name: ' Felix '
    }. Done (function (res) {
      if (Res.code = =) {
        Console.log (5- Count + '. Data is: ' + json.stringify (res.data);
      }
    });

    Count--;
  },4000);

};

In this code, I created a proxy object, can cache Ajax request 10s, with a timer called the proxy object five times get method to send the same request, the final printing effect is as follows:

As a result, the entire code executes 24s, and the time that the agent sends the request is 4s, 8s, 12s, 16s and 20s. Because the agent's cache is valid for 10s, and 4s is the first to send the request, the real Ajax request will definitely be sent at this time; When the same request is sent by the agents of the 8s and the 12s, the cache is still valid due to the fact that the cache time is only over 4s and 8s. Neither of these points sent the actual Ajax request; But when the 16s request is sent, the cache time for the first request is over 12s, the cache is invalidated, so the agent sends a real AJAX request, and the cache is refreshed, and the first 20s request is in the most recent cache valid time , so no actual AJAX requests are sent. Finally in the network can see the agent sent 5 requests, but only 2 service, if the cache effective time to extend, can reduce the number of requests backstage, this is the cache agent for front-end performance improvement key.

Hopefully this demo will give you a clearer idea of how caching proxies work.

4. This paper concludes

This article in the 1th part of the implementation of the summary in my own work to apply a lot, at least did not encounter any problems, but also may be I did not encounter, after all, that component implementation still has a lot of constraints. The 2nd part of the implementation I have just applied to the work, just have a feature I consider the need for caching, so I wrote a relatively simple implementation, although simple, but has been able to solve my problem, the actual work is the case, some things do not need to detail in advance on the design is perfect, Solving the problem first, then coming back to refactoring when you meet new problems, is sometimes a better way to work. The next blog introduces another use of the cache proxy components of the implementation of ideas, and provincial and municipal cascade similar functions, but I think is written in a more versatile, and the HTML structure and CSS as far as possible to separate components, please continue to pay attention to.

This is the jquery Ajax two-time encapsulation and AJAX cache Agent components: Ajaxcache Detailed is a small series to share all the content, hope to give you a reference, but also hope that we support cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.