Second encapsulation of jquery ajax and ajax cache proxy components: detailed explanation of AjaxCache and jqueryajaxcache

Source: Internet
Author: User
Tags delete cache

Second encapsulation of jquery ajax and ajax cache proxy components: detailed explanation of AjaxCache and jqueryajaxcache

Although jquery's newer APIs are already very useful, there is still a need for secondary encapsulation in actual work. The benefits include: 1. The APIS after secondary encapsulation are more concise, it is more in line with personal habits; 2. You can perform some unified processing on ajax operations, such as appending random numbers or other parameters. At the same time, we will also find that there are some ajax request data that does not require high real-time performance, even if we cache the data from the first request, then, when the same request is initiated again, returning the previously cached data will not affect related functions. This manual Cache control reduces the number of ajax requests, more or less, it can also help us improve the performance of web pages. This article introduces my own practices on these two issues.

Click to download the code(Note: Because ajax is used, it cannot be run under the file protocol and must be run under http)

1. encapsulate jquery's ajax

In fact, this part of related content has been introduced in a previous blog, but it is only referenced and not described in detail, in addition, the implementation of the ajax cache Proxy component is also based on the ajax component after the secondary encapsulation, so it is necessary to describe it in detail here, although the implementation is not complex (see the Notes ):

Define (function (require, exports, module) {var $ = require ('jquery '); // create an ajax object function create (_ url, _ method, _ data, _ async, _ dataType) {// Add a random number if (_ url. indexOf ('? ')>-1) {_ url = _ url +' & rnd = '+ Math. random ();} else {_ url = _ url + '? Rnd = '+ Math. random () ;}// add an ajax ID for the request to distinguish ajax from non-ajax request_url + = '& _ ajax = 1' in the background '; // return the ajax object created by jquery so that the object can be obtained externally through //. done. fail. always to add a callback // to keep the easy-to-use part of jquery ajax. return $. ajax ({url: _ url, dataType: _ dataType, async: _ async, method: _ method, data: _ data });} // ajax is the globally unique instance of this component. Its instance method is added through the following cyclic code // The parameters of each ajax instance method are configured in the methods object: // name: method Name // method: http request method, get or post // async: asynchronous when sending the request // dataType: 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, ype: 'json'}, {name: 'syncpost', method: 'post', async: false, dataType: 'json'}]; // because the logic for creating ajax for each instance method that needs to be provided externally in the second encapsulation is the same // you can define each instance method in this way // the key code is the one in the following code immediately the called function // it returns a new closure function as the 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 * The first represents the address to be requested * The second represents the data to be submitted to the background, which is an object, such as {param1: 'value1 '} * indicates the third data type returned by the backend. The most common data type is html or json. this parameter is not required in most cases, 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 tasks of this Ajax component are:
1) provide uniform random number parameters and ajax request identifiers;
2) The jquery api is packaged to provide clearer and clearer methods.

Usage:

Define (function (require, exports, module) {var Ajax = require ('mod/ajax '); // request the html content Ajax.html ('html/demo ', {param1: 'value1', param2: 'value2 '}). done (function (response) {// callback for successful request }). fail (function () {// callback for request failure }). always (function () {// callback completed by the request}); // request json data Ajax in GET mode. get ('api/demo', {param1: 'value1', param2: 'value2 '}). done (function (response) {// callback for successful request }). fail (function () {// callback for request failure }). always (function () {// callback completed by the request}); // request json data Ajax in POST mode. post ('api/demo', {param1: 'value1', param2: 'value2 '}). done (function (response) {// callback for successful request }). fail (function () {// callback for request failure }). always (function () {// callback completed by the request}); // send a synchronous request in GET mode to obtain json data Ajax. syncGet ('api/demo', {param1: 'value1', param2: 'value2 '}). done (function (response) {// callback for successful request }). fail (function () {// callback for request failure }). always (function () {// callback completed by the request}); // send a synchronous request in POST mode to obtain json data Ajax. syncPost ('api/demo', {param1: 'value1', param2: 'value2 '}). done (function (response) {// callback for successful request }). fail (function () {// callback for request failure }). always (function () {// callback for request Completion });});

Because the object returned by each instance method of this component is $. objects Created by ajax, so we can use them as usual. done. fail. always to add callback, just use $. ajax is no different. Why do APIs need to be designed as html, get, post, syncGet, and syncPost methods, and even dataType is basically fixed?

That's because in the project, we can completely agree that only the two types of ype html or json can be used for asynchronous requests. Other dataType is not allowed, the current web project methods are enough. At least I have never met the situation where I have to use another ype. In addition, in actual work, html, get, post, syncGet, the syncPost Methods cover almost all of the asynchronous requests we need. Whenever we use ajax, we only need to consider get or post, synchronous or asynchronous, the requests are html or json, which can solve each problem. Of course, in jsonp and rest APIs, this component is not serving them, but also its limitations. It is also intended to be used in traditional web projects.

2. ajax cache proxy

To implement a simple ajax cache Proxy component, you must first understand the role of this cache proxy. This article begins with the application scenario of the cache Proxy: when a cache proxy is used to initiate a request, the data is cached after the request is successful, and then the cached data is directly returned when the same request is initiated again, the cache proxy controls when a request is sent to the backend to load data, and when a request is not sent to directly read the previously loaded data from the cache. To implement a simple cache proxy, there are three problems to solve:

1) The proxy object must have the same API as the proxy object
Taking the preceding Ajax component as an example, it provides the html, get, post, syncGet, and syncPost methods, so its proxy object must also have these methods and call methods, all input parameters must be completely consistent. Only in this way, when we use a proxy object, there is no difference with using the original component object. In addition, in the cache proxy, the original component object must be called to send ajax requests under certain conditions. If the interfaces are different, the call methods and parameters are different, how can we ensure that the original component object can be correctly called internally? Another benefit of this condition is that when we do not want to use a proxy object next time, we can replace the proxy object with the original component object at the minimum cost.
This is actually the basic requirement of the proxy mode in the design mode.

2) cache indexes during cache data storage
That is to say, what indexes can we use to ensure that the data in the same request is cached and can be found based on the request information next time? The difference between ajax cache and other caches lies in that the requested address may contain variable parameter values. If the parameters behind the same address are different, the corresponding request results may not be the same, for the sake of simplicity, you can consider unifying the request address and request parameters as cache indexes so that you can easily manage the cache. Considering other variability, there are also some other requirements. For details, see the annotations in the component implementation section below.

3) cache Validity Period
Although the cache proxy to be implemented is very simple, this issue must be taken into account. Each cache proxy instance may be able to cache data for a period of time that is not necessarily the same, and some may only cache data for a few minutes, some may cache for dozens of minutes. When the cache time becomes invalid, the cache proxy must delete the original cache and load the data again.

Based on the Ajax component in the first part, the code of the cache Proxy component AjaxCache is as follows (with comments ):

Define (function (require, exports, module) {var $ = require ('jquery '); var Ajax = require ('mod/ajax '); // cache list var cache ={};/*** generate cache index: * because the index is generated based on url and data (data is an object, stores data that Ajax needs to be submitted to the background. * to store the same url, the same data can be effectively cached. * do not include variable parameter values in the url or data, such as a random number * For example, there is a request: * url: aaa/bbb/cccc? R = 0.312738 * data: {name: 'json'} * The r behind the url is a random number. Each time an external request is initiated, r value changes * Because r is different each time, the cache index will eventually be different, and the result cache will not hit * Note: random numbers can be placed in the original Ajax component. ** In addition, if the same interface is used, it is best to unify the url path type on the same page, or both are relative paths, either an absolute path * or 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 validity period. The default value is 60 Minutes. var proxy ={}; for (var I in Ajax) {if (Object. prototype. hasOwnProperty. call (Ajax, I )) {// define the proxy for each Ajax component instance method on the proxy object // note the function expression called immediately // it returns a closure function that is the final proxy method proxy [I] = (function (I) {return function () {var _ url = arguments [0], _ data = arguments [1], cacheKey = generateCacheKey (_ 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 validity period, the cache is valid isCacheValid = true ;} else {// otherwise, delete cache [cacheKey];} if (isCacheValid) {// simulate an asynchronous task to return cached data // delay the object through $ defer, you can ensure that the objects returned by the simulation task have the same API as those returned by the original Ajax component call. // This is the key of proxy: the proxy object and the object to be proxy should have the same API // only when we cancel the proxy, will not modify those components that use the proxy var $ defer = $. deferred (); setTimeout (function () {$ defer. resolve (cacheItem. res) ;}, 10); return $. when ($ defer);} // when the cache is invalid or there is no cache, call the method of the same name of the original Ajax component to request data return Ajax [I]. apply (Ajax, arguments ). done (function (res) {// cache the result after the request is successful, and record the current time as the cache start time [cacheKey] = {res: res, cacheStartTime: + new Date () }}) ;}} (I) ;}} return proxy ;};});

In the first part and the implementation of this part, the most important thing is the function expression that is called immediately. Without the closure returned by this function, the code will be faulty, this is also a classic problem of applying closures in loops.

3. Demo results

To demonstrate the effect of the cache proxy, I made a demonstration:
 
Among them, ajax. js is the implementation of the first part, and ajaxCache. js is the implementation of the second part. It shows the html/demo.html in the corresponding code on the page, and the relevant js is js/app/demo. js:

Define (function (require, exports, module) {var AjaxCache = require ('mod/ajaxcaccache '); // create a proxy object var Ajax = new ajaxCache ({cacheInterval: 10*1000}); var count = 5; console. log ('time point: '+ 0 +' s, start with the timer! '); Var t = setInterval (function () {if (count = 0) {console. log ('time point: '+ (5-count + 1) * 4 +' s, the timer ends! '); Return clearInterval (t);} else {console. log ('time point: nth + (5-count + 1) * 4 +'s: ');} Ajax. get ('.. /api/data. json ', {name: 'Felix '}). done (function (res) {if (res. code == 200) {console. log (5-count + '. data is: '+ JSON. stringify (res. data) ;}}); count -- ;}, 4000 );});

In this Code, I created a proxy object that can cache ajax requests for 10 s and use a timer to call the proxy object five get methods to send the same request, the final print effect is as follows:

As a result, the entire code is executed for 24 s, and the time when the proxy sends the request is 4th s, 8th s, 12th s, 16s, and 20th s, respectively. Because the cache validity period of the proxy is 10 s and the 4s is the first request to be sent, the actual ajax request will be sent at this time; when the agent of the 8s and 12s sends the same request, the cache is valid because the cache time is only 4s and 8 s away, no actual ajax request is sent at these two time points. However, when the 16s request is sent, the cache time for the first request is past 12 s, and the cache has expired, therefore, the proxy sent a real ajax request, and the cache was refreshed. The 20 s request was still in the latest cache validity period, so no actual ajax request was sent. Finally, in the network, we can see that the proxy sent 5 requests but only requested 2 services. If the cache validity period is extended, the number of requests in the backend can be reduced, this is also the key to improving the front-end performance of the cache proxy.

We hope this demonstration will give you a clearer understanding of the role of the cache proxy.

4. Summary

The implementation summarized in part 1 of this Article has been applied a lot in my own work. At least I have not encountered any problems, but it may be that I have not encountered any problems. After all, there are still many constraints on the implementation of that component. I have just applied the implementation of part 1 to my work. I just wrote a simple implementation, although simple, because of the necessity of caching, however, my problem can be solved. The actual work is like this. Some things do not need to be designed perfectly beforehand. First, we should solve the problem, it is sometimes a better way to work when you encounter a new problem. The next blog introduces the implementation idea of another component that uses the cache proxy, which is similar to the provincial and municipal functions, but what I want is to write more universal, components that can be separated from the html structure and css as much as possible. Please stay tuned.

The above section provides a secondary encapsulation of jquery ajax and ajax cache proxy components: the details of AjaxCache are all the content that I have shared with you. I hope you can give me a reference, we also hope that you can support the customer's home.

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.