ホームページ >ウェブフロントエンド >jsチュートリアル >Jquery Promise は画像を 1 つずつロードする_jquery を実装します

Jquery Promise は画像を 1 つずつロードする_jquery を実装します

WBOY
WBOYオリジナル
2016-05-16 15:32:311581ブラウズ

Promise は CommonJS の仕様の 1 つであり、resolve、reject、done、fail、then などのメソッドがあり、コードのフローを制御し、関数の多層ネストを回避するのに役立ちます。現在、Web 開発では非同期性がますます重要になっており、この種の非線形実行プログラミングは、開発者がコードの実行プロセスをより適切に制御できるようになります。 as jQuery すべてのライブラリはすでにこのオブジェクトを実装しており、年末にリリースされる ES6 も Promise をネイティブに実装します。

JavaScript デザインパターン演習 - 画像のプリロードのプロキシ モードでは、画像のプリロード機能はプロキシ モードを使用して実装されます。

ここでさらに一歩進んで、連続した写真を 1 枚ずつ読み込む機能を完成させましょう。

機能:

1. 写真を 1 枚ずつ読み込みます。

2. 読み込みエラー。タイムアウト後に読み込み失敗画像が表示されます。

機能要件に関しては、ステータスイベントや完了時にコールバック関数をロードする処理が必ず発生しますが、これはコードの混乱を招くだけでなく、さまざまな原則を破壊する可能性があるため、通常のメソッドを使用して記述することはやめます。 。このステータス通知の特性を考慮すると、Promise は基本的にサブスクリプション・パブリッシュ設計パターンの一種であり、現在では jquery に付属する Promise を使用してこの機能を開発しています。

1. 画像をロードするためのプロキシ作成機能を完了します。これにより、ロードのタイムアウト、失敗、成功、およびキャンセルの監視機能を備えたプロキシを生成できます。

 function createLoadImgProxy(){
  var imgCache = new Image();
  var dfd = $.Deferred();
  var timeoutTimer;
  //开始加载超时监控,超时后进行reject操作
  function beginTimeoutWatcher(){
   timeoutTimer = setTimeout(function(){
   dfd.reject('timeout');
   }, 10000);
  }
  //结束加载超时监控
  function endTimeoutWatcher(){
   if(!timeoutTimer){
   return;
   }
   clearTimeout(timeoutTimer);
  }
  //加载完成事件处理,加载完成后进行resolve操作
  imgCache.onload = function(){
   dfd.resolve(this.src);
  };
  //加载终止事件处理,终止后进行reject操作
  imgCache.onabort = function(){
   dfd.reject("aborted");
  };
  //加载异常事件处理,异常后进行reject操作
  imgCache.onerror = function(){
   dfd.reject("error");
  };
  return function(eleImg, src){
   dfd.always(function(){
   //加载完成或加载失败都要终止加载超时监控
   endTimeoutWatcher();
   }).done(function(src){
   //加载完成后,往图片元素上设置图片
   loadImg(eleImg, src);
   }).fail(function(msg){
   //加载失败后,往图片元素上设置失败图片
   loadImg(eleImg, 'loadFailed.jpg');
   });
   loadImg(eleImg, 'loading.gif');
   imgCache.src = src;
   //开始进行超时加载监控
   beginTimeoutWatcher();
   return dfd.promise();
  };
  }

このうち、Deferred オブジェクトは次の方法で作成されます

コードをコピーします コードは次のとおりです:

var dfd = $.Deferred();

Deferred オブジェクトは、resolve メソッドを通じて完了イベントをトリガーし、done メソッドを使用して完了イベントに応答します。

読み込みが成功するとイベントが完了します。

コードをコピーします コードは次のとおりです:

imgCache.onload = function(){
dfd.resolve(this.src);
};

と読み込み完了時のレスポンス処理は要素に画像を設定するコードです。 以下のコードは上記のチェーン記述メソッドを逆アセンブルしたものです。

コードをコピー コードは次のとおりです:

dfd.done(関数(src){
//読み込み完了後、画像要素に画像を設定します
LoadImg(eleImg, src);
});

Deferred オブジェクトは、reject メソッドを通じて拒否イベントをトリガーし、fail メソッドを使用して拒否イベントに応答し、読み込みが失敗したことを示します。

ロード時のタイムアウト、終了、例外のイベントを拒否します。                                                                       

 //开始加载超时监控,超时后进行reject操作
  function beginTimeoutWatcher(){
   timeoutTimer = setTimeout(function(){
   dfd.reject('timeout');
   }, 10000);
  }
  //加载终止事件处理,终止后进行reject操作
  imgCache.onabort = function(){
   dfd.reject("aborted");
  };
  //加载异常事件处理,异常后进行reject操作
  imgCache.onerror = function(){
   dfd.reject("error");
  };
読み込み失敗時の応答処理、失敗画像の設定などを行います。                                                          


 dfd.fail(function(msg){
   //加载失败后,往图片元素上设置失败图片
   loadImg(eleImg, 'loadFailed.jpg');
   });
プロキシ関数の最後で、deferred Promise オブジェクトを返します。このオブジェクトは、次のイメージのロードを容易にするために、呼び出し元へのロードの完了と失敗のステータスを監視するために使用されます。

return dfd.promise();


2. 1 つずつ連続読み込み

//一张一张的连续加载图片
  //参数:
  // srcs: 图片路径数组
  function doLoadImgs(srcs){
  var index = 0;
  (function loadOneByOne(){
   //退出条件
   if(!(s = srcs[index++])) {
   return;
   }
   var eleImg = createImgElement();
   document.getElementById('imgContainer').appendChild(eleImg);
   //创建一个加载代理函数
   var loadImgProxy = createLoadImgProxy();
   //在当前图片加载或失败后,递归调用,加载下一张
   loadImgProxy(eleImg, s).always(loadOneByOne);
  })();
  }
loadOneByOneの再帰読み込み関数を作成します。

読み込みエージェントはまず内部で作成され、エージェントがイメージを読み込んだ後、成功か失敗に関係なく、loadOneByOne 関数が再帰的に呼び出され、次のイメージが読み込まれます。

キーは、プロキシ関数によって返された Promise オブジェクトにあります。読み込みが完了した後 (成功または失敗)、.always メソッドを使用して、loadOneByOne を再帰的に呼び出し、次の画像を読み込みます。

コードをコピーします コードは次のとおりです:
loadImgProxy(eleImg, s).always(loadOneByOne);

至此完成。

采用了promise模式后,callback函数不见了,维护状态的函数和内部变量也不见了,代码更清晰简单,使得代理函数和本地函数之间的一致性得到保护。

完整代码:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 </head>
 <body>
 <button id='btnLoadImg'>加载图片</button>
 <br>
 <div id='imgContainer'>
 </div>
 <br>
 <script type='text/javascript' src="./jquery-1.11.3.min.js"></script>
 <script type='text/javascript'>
  var imgSrcs = [
  'http://img.wanchezhijia.com/A/2015/3/20/17/11/de63f77c-f74f-413a-951b-5390101a7d74.jpg',
  'http://www.newbridgemotorsport.com/files/6413/9945/0406/IMG_3630.jpg',
  'http://www.carsceneuk.com/wp-content/uploads/2015/03/88y9989.jpg',
  'http://mfiles.sohu.com/20130223/5ff_403b2e7a_7a1f_7f24_66eb_79e3f27d58cf_1.jpg',
  'http://img1.imgtn.bdimg.com/it/u=2678963350,1378052193&fm=21&gp=0.jpg'
  ];
  $(document).ready(function(){
  $('#btnLoadImg').bind('click', function(){
   doLoadImgs(imgSrcs);
  });
  });
  //创建img标签
  //这里用自执行函数加一个闭包,是为了可以创建多个id不同的img标签。
  var createImgElement = (function(){
  var index = 0;
  return function() {
   var eleImg = document.createElement('img');
   eleImg.setAttribute('width', '200');
   eleImg.setAttribute('heght', '150');
   eleImg.setAttribute('id', 'img' + index++);
   return eleImg;
  };
  })();
  function loadImg(img, src) {
  img.src = src;
  }
  function createLoadImgProxy(){
  var imgCache = new Image();
  var dfd = $.Deferred();
  var timeoutTimer;
  //开始加载超时监控,超时后进行reject操作
  function beginTimeoutWatcher(){
   timeoutTimer = setTimeout(function(){
   dfd.reject('timeout');
   }, 10000);
  }
  //结束加载超时监控
  function endTimeoutWatcher(){
   if(!timeoutTimer){
   return;
   }
   clearTimeout(timeoutTimer);
  }
  //加载完成事件处理,加载完成后进行resolve操作
  imgCache.onload = function(){
   dfd.resolve(this.src);
  };
  //加载终止事件处理,终止后进行reject操作
  imgCache.onabort = function(){
   dfd.reject("aborted");
  };
  //加载异常事件处理,异常后进行reject操作
  imgCache.onerror = function(){
   dfd.reject("error");
  };
  return function(eleImg, src){
   dfd.always(function(){
//   alert('always end');
   //加载完成或加载失败都要终止加载超时监控
   endTimeoutWatcher();
   }).done(function(src){
//   alert('done end');
   //加载完成后,往图片元素上设置图片
   loadImg(eleImg, src);
   }).fail(function(msg){
//   alert('fail end:' + msg);
   //加载失败后,往图片元素上设置失败图片
   loadImg(eleImg, 'loadFailed.jpg');
   });
   loadImg(eleImg, 'loading.gif');
   imgCache.src = src;
   //开始进行超时加载监控
   beginTimeoutWatcher();
   return dfd.promise();
  };
  }
  //一张一张的连续加载图片
  //参数:
  // srcs: 图片路径数组
  function doLoadImgs(srcs){
  var index = 0;
  (function loadOneByOne(){
   //退出条件
   if(!(s = srcs[index++])) {
   return;
   }
   var eleImg = createImgElement();
   document.getElementById('imgContainer').appendChild(eleImg);
   //创建一个加载代理函数
   var loadImgProxy = createLoadImgProxy();
   //在当前图片加载或失败后,递归调用,加载下一张
   loadImgProxy(eleImg, s).always(loadOneByOne);
  })();
  }
 </script>
 </body>
</html>
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。