Rumah > hujung hadapan web > tutorial js > Enkapsulasi sekunder komponen proksi cache ajax dan ajax jquery: penjelasan terperinci AjaxCache_jquery

Enkapsulasi sekunder komponen proksi cache ajax dan ajax jquery: penjelasan terperinci AjaxCache_jquery

WBOY
Lepaskan: 2016-05-16 15:06:00
asal
1917 orang telah melayarinya

Walaupun API jquery yang lebih baru sudah sangat mudah digunakan, masih perlu melakukan enkapsulasi sekunder dalam kerja sebenar: 1. API selepas enkapsulasi sekunder lebih ringkas dan lebih sesuai dengan tabiat penggunaan peribadi. ; 2. Anda boleh melakukan beberapa pemprosesan bersatu pada operasi ajax, seperti menambahkan nombor rawak atau parameter lain. Pada masa yang sama di tempat kerja, kami juga akan mendapati bahawa terdapat beberapa data yang diminta ajax yang tidak mempunyai keperluan masa nyata yang tinggi Walaupun kami menyimpan data yang diminta buat kali pertama, maka apabila permintaan yang sama dikeluarkan semula, kami akan terus mendapatkan data yang dicache sebelum ini tidak akan memberi kesan kepada fungsi yang berkaitan Melalui kawalan cache manual ini, permintaan ajax dikurangkan, yang juga boleh membantu kami meningkatkan prestasi halaman web. Artikel ini memperkenalkan pendekatan saya sendiri kepada dua isu ini. Saya mengalu-alukan pertukaran dan pembetulan.

Klik untuk memuat turun kod (Nota: Kerana ajax digunakan, ia tidak boleh dijalankan di bawah protokol fail dan mesti dijalankan di bawah http)

1. Ajax merangkum jquery

Malah, kandungan berkaitan bahagian ini telah diperkenalkan dalam blog sebelum ini, tetapi ia hanya dipetik tanpa penjelasan terperinci Selain itu, pelaksanaan komponen proksi cache ajax juga berdasarkan komponen ajax selepas pengkapsulan sekunder ini , jadi ada Perlu menjelaskannya secara terperinci di sini, walaupun pelaksanaannya tidak rumit (lihat ulasan untuk butiran):

define(function (require, exports, module) {

  var $ = require('jquery');

  //根据关键的几个参数统一创建ajax对象
  function create(_url, _method, _data, _async, _dataType) {
    //添加随机数
    if (_url.indexOf('?') > -1) {
      _url = _url + '&rnd=' + Math.random();
    } else {
      _url = _url + '?rnd=' + Math.random();
    }

    //为请求添加ajax标识,方便后台区分ajax和非ajax请求
    _url += '&_ajax=1';

    //返回jquery创建的ajax对象,以便外部拿到这个对象以后可以通过
    //.done .fail .always来添加回调
    //这么做是为了保留jquery ajax中好用的部分
    return $.ajax({
      url: _url,
      dataType: _dataType,
      async: _async,
      method: _method,
      data: _data
    });
  }

  //ajax就是本组件全局唯一的实例,它的实例方法通过后面的循环代码添加
  //methods对象配置ajax各个实例方法的参数:
  //name: 方法名称
  //method: http请求方法,get or post
  //async: 发送请求时是否异步
  //dataType: 返回的数据类型,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,
        dataType: 'json'
      }
    ];

  //由于二次封装需要对外提供的每个实例方法创建ajax的逻辑是相同的
  //所以通过这种方式统一定义各个实例方法
  //关键代码为下面代码中的那个立即调用的函数
  //它返回了一个新的闭包函数作为实例方法
  for (var i = 0, l = methods.length; i < l; i++) {
    ajax[methods[i].name] = (function (i) {
      return function () {
        /**
         * 每个实例方法接收三个参数
         * 第一个表示要请求的地址
         * 第二个表示要提交到后台的数据,是一个object对象,如{param1: 'value1'}
         * 第三个表示后台返回的数据类型,最最常用的就是html or json,绝大部分情况下这个参数不用传,会使用methods里面定义的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;
});

Salin selepas log masuk
Perkara utama komponen Ajax ini lakukan ialah:
1) Sediakan parameter nombor rawak dan pengecam permintaan ajax secara seragam; 2) API jquery dibungkus, dan kaedah yang disediakan kepada dunia luar adalah lebih jelas dan jelas.
Penggunaan:

define(function (require, exports, module) {

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

  //以GET方式请求html内容
  Ajax.html('html/demo', {
    param1: 'value1',
    param2: 'value2'
  }).done(function(response){
    //请求成功的回调
  }).fail(function(){
    //请求失败的回调
  }).always(function(){
    //请求完成的回调
  });

  //以GET方式请求json数据
  Ajax.get('api/demo', {
    param1: 'value1',
    param2: 'value2'
  }).done(function(response){
    //请求成功的回调
  }).fail(function(){
    //请求失败的回调
  }).always(function(){
    //请求完成的回调
  });

  //以POST方式请求json数据
  Ajax.post('api/demo', {
    param1: 'value1',
    param2: 'value2'
  }).done(function(response){
    //请求成功的回调
  }).fail(function(){
    //请求失败的回调
  }).always(function(){
    //请求完成的回调
  });

  //以GET方式发送同步请求,获取json数据
  Ajax.syncGet('api/demo', {
    param1: 'value1',
    param2: 'value2'
  }).done(function(response){
    //请求成功的回调
  }).fail(function(){
    //请求失败的回调
  }).always(function(){
    //请求完成的回调
  });

  //以POST方式发送同步请求,获取json数据
  Ajax.syncPost('api/demo', {
    param1: 'value1',
    param2: 'value2'
  }).done(function(response){
    //请求成功的回调
  }).fail(function(){
    //请求失败的回调
  }).always(function(){
    //请求完成的回调
  });

});
Salin selepas log masuk

由于这个组件的每个实例方法返回的对象就是$.ajax创建的对象,所以我们完全可以照常使用.done .fail .always来添加回调,就跟直接用$.ajax没有任何区别。为什么API要设计成html, get, post, syncGet, syncPost这几个方法,而且连dataType基本都是固定的?

那是因为在项目中,我们完全可以约定在异步请求的时候只能用html或json这两种dataType,其它dataType不允许,现在的web项目这两种方式已经完全够用了,至少我没有碰到过非得使用别的dataType不可的情况;而且在实际工作当中html, get, post, syncGet, syncPost这几个方法几乎能够涵盖我们需要的所有异步请求的场景,每当我们要用ajax的时候,无非考虑的就是get还是post,同步还是异步,请求的是html还是json这三个问题,通过它们就能把每个问题都解决了。当然jsonp,rest API这两种情况就另说了,这个组件不是为它们服务的,这也是它的局限性,它还是倾向于在传统的web项目中使用。

2. ajax缓存代理

要实现一个简单的ajax缓存代理组件,首先要清楚这个缓存代理的作用,在本文开篇说到过缓存代理的应用场景:当使用缓存代理第一个发起某个请求时,在请求成功后将数据缓存下来,然后当再次发起相同请求时直接返回之前缓存的数据,缓存代理的作用是控制何时发送请求去后台加载数据,何时不发送请求直接从缓存中读取之前加载的数据。为了实现一个简单的缓存代理,有三个问题要解决:

1)代理对象必须与被代理的对象有相同的API
拿前面的Ajax组件来说,它提供有html, get , post, syncGet, syncPost方法,那么它的代理对象也必须同时具有这些方法,而且调用方式,传入参数都必须完全一致,只有这样,当我们在使用代理对象的时候,就跟在使用原组件对象没有区别。而且在缓存代理内部,在某些条件下是需要调用原组件对象发送ajax请求的,如果接口不同,调用方式不同,参数不同,如何能保证内部能够正确调用原组件对象呢?这个条件还有一个好处,就是当我们下次不想使用代理对象的时候,能够以最小的代价将代理对象替换为原组件对象。
这一点其实是设计模式中代理模式的基本要求。

2)缓存数据存储时的缓存索引问题
也就是说我们以什么样的索引才能保证同一个请求的数据在缓存之后,下次查找时还能根据请求信息查找到呢?ajax缓存有别于其它缓存的地方在于它请求的地址可能包含可变的参数值,同一个地址如果后面的参数不同,那么对应的请求结果也就不一定相同,所以简单起见,可以考虑把请求地址跟请求参数统一作为缓存索引,这样就能对缓存进行简单管理。同时考虑到其它可变性,还应有其它的一些要求,详见后面组件实现中的注释说明。

3)缓存有效时间
虽然要实现的缓存代理很简单,但是这个问题一定是要考虑的,每个缓存代理实例,能够缓存数据的有效时间不一定相同,有的可能只缓存几分钟,有的可能缓存几十分钟,当缓存时间失效时,缓存代理就得删除原来的缓存,然后重新去加载数据才行。

综合这些问题,基于第一部分的Ajax组件,最终实现的缓存代理组件AjaxCache的代码如下(有注释详解):

define(function (require, exports, module) {

  var $ = require('jquery');
  var Ajax = require('mod/ajax');

  //缓存列表
  var cache = {};

  /**
   * 生成缓存索引:
   * 由于索引是根据url和data生成的(data是一个对象,存放Ajax要提交到后台的数据)
   * 所以要想同一个url,同样的data能够有效地使用缓存,
   * 切勿在url和data中包含每次可变的参数值,如随机数等
   * 比如有一个请求:
   * url: aaa/bbb/cccc&#63;r=0.312738
   * data: {name: 'json'}
   * 其中url后面的r是一个随机数,每次外部发起这个请求时,r的值都会变化
   * 由于r每次都不同,最终会导致缓存索引不相同,结果缓存就无法命中
   * 注:随机数可放置在原始的Ajax组件内
   *
   * 还有:如果是同一个接口,最好在同一个页面内,统一url的路径类型,要么都是相对路径,要么都是绝对路径
   * 否则也会导致缓存无法有效管理
   */
  function generateCacheKey(url, data) {
    return url + $.param(data);
  }

  return function (opts) {
    opts = opts || {};

    var cacheInterval = opts.cacheInterval || (1000 * 60 * 60);//缓存有效时间,默认60分钟

    var proxy = {};
    for (var i in Ajax) {
      if (Object.prototype.hasOwnProperty.call(Ajax, i)) {
        //在proxy对象上定义Ajax组件每一个实例方法的代理
        //注意这个立即调用的函数表达式
        //它返回了一个闭包函数就是最终的代理方法
        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) {
                //如果请求时间跟缓存开始时间的间隔在缓存有效时间范围内,就表示缓存是有效的
                isCacheValid = true;
              } else {
                //否则就把缓存清掉
                delete cache[cacheKey];
              }
            }

            if (isCacheValid) {
              //模拟一个异步任务来返回已经缓存的数据
              //通过$defer延迟对象,可以保证这个模拟任务返回的对象跟原始Ajax组件调用返回的对象有相同的API
              //这是代理的关键:代理对象与被代理的对象应该具有相同API
              //只有这样当我们取消代理的时候,不会对那些用了代理的组件进行修改
              var $defer = $.Deferred();
              setTimeout(function () {
                $defer.resolve(cacheItem.res);
              }, 10);
              return $.when($defer);
            }

            //缓存失效或者没有缓存的时候调用原始的Ajax组件的同名方法去后台请求数据
            return Ajax[i].apply(Ajax, arguments).done(function (res) {
              //在请求成功之后将结果缓存,并记录当前时间作为缓存的开始时间
              cache[cacheKey] = {
                res: res,
                cacheStartTime: +new Date()
              }
            });
          }
        })(i);
      }
    }
    return proxy;
  };
});
Salin selepas log masuk

在第一部分和本部分的实现中,最关键的都是那个立即调用的函数表达式,没有它返回的闭包,代码就会有问题,这也是闭包在循环中应用的经典问题。

3. 演示效果

为了说明缓存代理的使用效果,我做了一个演示效果:
Enkapsulasi sekunder komponen proksi cache ajax dan ajax jquery: penjelasan terperinci AjaxCache_jquery
其中的ajax.js就是第一部分的实现,ajaxCache.js就是第二部分的实现,演示页面对应代码中的html/demo.html,相关js是js/app/demo.js:

define(function (require, exports, module) {

  var AjaxCache = require('mod/ajaxCache');

  //创建代理对象
  var Ajax = new AjaxCache({
    cacheInterval: 10 * 1000
  });

  var count = 5;

  console.log('时间点:第' + 0 + 's,定时器开始!');
  var t = setInterval(function(){
    if(count == 0) {
      console.log('时间点:第' + (5 - count + 1) * 4 + 's,定时器结束!');
      return clearInterval(t);
    } else{
      console.log('时间点:第' + (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);

});
Salin selepas log masuk

Dalam kod ini, saya mencipta objek proksi yang boleh menyimpan permintaan ajax selama 10 saat saya menggunakan pemasa untuk memanggil kaedah dapatkan objek proksi lima kali untuk menghantar permintaan yang sama.
Enkapsulasi sekunder komponen proksi cache ajax dan ajax jquery: penjelasan terperinci AjaxCache_jquery
Berdasarkan keputusan, keseluruhan kod telah dilaksanakan selama 24 saat, dan titik masa apabila ejen menghantar permintaan adalah masing-masing saat ke-4, ke-8, ke-12, ke-16 dan ke-20. Memandangkan masa sah cache proksi ialah 10s, dan 4s adalah kali pertama permintaan dihantar, permintaan ajax sebenar pasti akan dihantar pada masa ini apabila proksi pada 8s dan 12s menghantar permintaan yang sama, sejak masa dari cache hanya melepasi 4s dan 8s, jadi cache masih sah Tiada permintaan ajax sebenar dihantar pada dua titik masa ini tetapi apabila permintaan 16s telah dihantar, 12s telah berlalu sejak masa cache permintaan pertama. dan cache telah tamat tempoh, jadi Proksi menghantar satu lagi permintaan ajax sebenar, dan kemudian cache telah disegarkan semula; Akhir sekali, anda boleh melihat dalam rangkaian bahawa proksi menghantar 5 permintaan, tetapi hanya meminta 2 perkhidmatan Jika masa sah cache dilanjutkan, bilangan permintaan latar belakang boleh dikurangkan Ini juga merupakan kunci untuk meningkatkan prestasi bahagian hadapan proksi caching.

Saya harap demonstrasi ini dapat memberi anda pemahaman yang lebih jelas tentang peranan proksi caching.

4. Ringkasan artikel ini

Pelaksanaan yang diringkaskan dalam bahagian pertama artikel ini telah banyak digunakan dalam kerja saya sendiri Sekurang-kurangnya saya tidak menghadapi sebarang masalah masih banyak kekangan. Saya baru saja mengaplikasikan pelaksanaan bahagian 2 pada kerja saya kebetulan ada satu fungsi yang saya anggap keperluan caching, jadi saya menulis pelaksanaan yang agak mudah, ia sudah boleh menyelesaikan masalah saya. Beginilah kerjanya. Sesetengah perkara tidak perlu direka bentuk dengan sempurna terlebih dahulu Menyelesaikan masalah itu dahulu, dan kemudian kembali untuk membina semula apabila masalah baharu dihadapi kadangkala merupakan cara yang lebih baik untuk bekerja. Blog seterusnya akan memperkenalkan idea pelaksanaan komponen lain menggunakan proksi cache, yang mempunyai fungsi yang sama dengan lata wilayah dan perbandaran Walau bagaimanapun, saya ingin menulis komponen yang lebih serba boleh yang boleh dipisahkan daripada struktur HTML dan CSS boleh.

Artikel di atas merangkum semula komponen proksi caching ajax dan ajax jquery: Penjelasan terperinci AjaxCache ialah semua kandungan yang dikongsi oleh editor saya harap ia dapat memberi rujukan kepada anda, dan saya harap anda akan menyokong Script Home.

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan