キューは、一方の端で挿入操作のみを許可し、もう一方の端で削除操作のみを許可する線形リストです。キューは先入れ先出し (FIFO) データ構造です。
キューはプログラム設計で非常に頻繁に使用されます。JavaScript はシングルスレッドであるため、一度に 1 つのタスクのみを実行でき、非同期メカニズムも混合されます。
次に問題:1. 非同期操作が実行されると、同期コードはまだ継続しており、同期コードは非同期に依存するため、当然エラーが発生します
2. 複数の同期タスクが異なる期間で呼び出されます
jQuery アニメーションでは、連続したアニメーション コードを記述することがよくあります
$book.animate({ opacity: 0.25, }).animate({ opacity: 0.5 }).animate({ opacity: 1 })
直感的には、最初のアニメーションが終了すると要素の不透明度が 0.25 になり、次に 2 番目のアニメーションが実行され始めて要素の不透明度が 0.5 になる、というようになります。しかし実際には、ここには本質的な問題があり、アニメーションは非同期で呼び出され、animate メソッドは同期的に実行されるため、jQuery はアニメーション用に特別に設計された queue メソッドも提供する必要があります。 キューは特殊な線形リストでもあり、JavaScript では配列を直接使用して、配列の末尾に要素を追加したり、shift() メソッドで要素を削除したりできます。配列の最初の要素。
function Queue() { this.dataStore = []; this.enqueue = enqueue; this.dequeue = dequeue; this.first = first; this.end = end; this.toString = toString; this.empty = empty; } /////////////////////////// // enqueue()方法向队尾添加一个元素: // /////////////////////////// function enqueue(element) { this.dataStore.push(element); } ///////////////////////// // dequeue()方法删除队首的元素: // ///////////////////////// function dequeue() { return this.dataStore.shift(); } ///////////////////////// // 可以使用如下方法读取队首和队尾的元素: // ///////////////////////// function first() { return this.dataStore[0]; } function end() { return this.dataStore[this.dataStore.length - 1]; } ///////////////////////////// // toString()方法显示队列内的所有元素 // ///////////////////////////// function toString() { var retStr = ""; for (var i = 0; i < this.dataStore.length; ++i) { retStr += this.dataStore[i] + "\n"; } return retStr; } //////////////////////// // 需要一个方法判断队列是否为空 // //////////////////////// function empty() { if (this.dataStore.length == 0) { return true; } else { return false; } } var q = new Queue(); q.enqueue("Aaron1"); q.enqueue("Aaron2"); q.enqueue("Aaron3"); console.log("队列头: " + q.first()); //("Aaron1"); console.log("队列尾: " + q.end()); //("Aaron3");
キューはリニア ストレージを使用するため、最初の人がチケットを購入すると、後続の人は自然に 1 スペースずつ進み、キュー全体が関与するなど、シーケンシャル ストレージにはいくつかの欠点があります。の各メンバーは前に進む必要がありますが、JavaScript のキューは配列によって記述されており、最下層がいくつかの欠点を解決しています。もちろん、単一リンクされたリスト構造の実装に使用できる配列など、検索アルゴリズムに関する問題もあります。ここでは JavaScript キューについてのみ説明します
jQuery をシミュレートし、キューを使用してアニメーションを実装します
<div id="div1" style="width:100px;height:50px;background:red;cursor:pointer;color:#fff;text-align:center;line-height:50px;">点击</div> (function($) { window.$ = $; })(function() { var rquickExpr = /^(?:#([\w-]*))$/; function aQuery(selector) { return new aQuery.fn.init(selector); } /** * 动画 * @return {[type]} [description] */ var animation = function() { var self = {}; var Queue = []; //动画队列 var fireing = false //动画锁 var first = true; //通过add接口触发 var getStyle = function(obj, attr) { return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, false)[attr]; } var makeAnim = function(element, options, func) { var width = options.width //包装了具体的执行算法 //css3 //setTimeout element.style.webkitTransitionDuration = '2000ms'; element.style.webkitTransform = 'translate3d(' + width + 'px,0,0)'; //监听动画完结 element.addEventListener('webkitTransitionEnd', function() { func() }); } var _fire = function() { //加入动画正在触发 if (!fireing) { var onceRun = Queue.shift(); if (onceRun) { fireing = true; //next onceRun(function() { fireing = false; _fire(); }); } else { fireing = true; } } } return self = { //增加队列 add: function(element, options) { Queue.push(function(func) { makeAnim(element, options, func); }); //如果有一个队列立刻触发动画 if (first && Queue.length) { first = false; self.fire(); } }, //触发 fire: function() { _fire(); } } }(); aQuery.fn = aQuery.prototype = { run: function(options) { animation.add(this.element, options); return this; } } var init = aQuery.fn.init = function(selector) { var match = rquickExpr.exec(selector); var element = document.getElementById(match[1]) this.element = element; return this; } init.prototype = aQuery.fn; return aQuery; }()); //dom var oDiv = document.getElementById('div1'); //调用 oDiv.onclick = function() { $('#div1').run({ 'width': '500' }).run({ 'width': '300' }).run({ 'width': '1000' }); };
テスト