Maison >interface Web >js tutoriel >Structures de données et algorithmes en JavaScript (2) : compétences Queue_javascript
Une file d'attente est une liste linéaire qui autorise uniquement les opérations d'insertion à une extrémité et les opérations de suppression à l'autre extrémité. La file d'attente est une structure de données First-In-First-Out (FIFO)
.La file d'attente est utilisée très fréquemment dans la conception de programmes. Étant donné que JavaScript est monothread, une seule tâche peut être exécutée à tout moment, et elle est également mélangée à un mécanisme asynchrone
.Alors le problème :
1. Lorsque l'opération asynchrone est exécutée, le code synchrone continue, alors le code synchrone dépend de l'asynchrone et des erreurs se produiront naturellement
2. Plusieurs tâches synchronisées sont appelées à différentes périodes
Dans l'animation jQuery, nous écrivons souvent un code d'animation continue
$book.animate({ opacity: 0.25, }).animate({ opacity: 0.5 }).animate({ opacity: 1 })
Le sentiment intuitif que nous avons est le suivant : une fois la première animation terminée, l'opacité de l'élément devient 0,25, puis la deuxième animation commence à être exécutée, et l'opacité de l'élément devient 0,5, et ainsi de suite. Mais en fait, il y a ici un problème essentiel. L'animation est appelée de manière asynchrone et la méthode d'animation est exécutée de manière synchrone, donc une file d'attente doit être conçue ici jQuery fournit également une méthode de file d'attente spécialement conçue pour l'animation
.
La file d'attente est également une liste linéaire spéciale.En JavaScript, nous pouvons utiliser directement des tableaux pour implémenter une telle conception. La méthode push() du tableau peut ajouter des éléments à la fin du tableau, et la méthode shift() peut supprimer les éléments. premier élément du tableau.
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");
La file d'attente utilise le stockage linéaire, il y a donc certains inconvénients du stockage séquentiel, comme faire la queue pour acheter des billets. Si le premier l'achète, les suivants avanceront naturellement d'un espace, ce qui implique toute la file d'attente. Chaque membre de doit avancer, mais la file d'attente de JavaScript est décrite par un tableau et la couche inférieure résout certaines lacunes. Bien sûr, il existe également des problèmes avec les algorithmes de recherche, tels que les tableaux qui peuvent être utilisés pour implémenter des structures de liste à chaînage unique, etc. Nous ne discutons ici que des files d'attente JavaScript
Simulez jQuery et utilisez des files d'attente pour implémenter une animation
<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' }); };
Test
<!doctype html><div id="div1" style="width:100px;height:50px;background:red;cursor:pointer;color:#fff;text-align:center;line-height:50px;" data-mce-style="width: 100px; height: 50px; background: red; cursor: pointer; color: #fff; text-align: center; line-height: 50px;">点击</div><script type="text/javascript"> (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' }); }; </script>