Data Structure and algorithm in JavaScript of ii: Queues
- 2020-06-15 07:47:47
- OfStack
Queue is a linear table that allows only insert operations on the 1 end and delete operations on the other. Queue is a first-in, first-out (ES1en-ES2en-ES3en-ES4en, FIFO) data structure
Queues are used very frequently in programming because javascript is single-threaded, so that only one task can be executed at any one time and the asynchronous mechanism is also involved.
So the question is:
1. If the synchronous code continues while the asynchronous operation is being executed, then the synchronous code relies on asynchrony, which naturally leads to errors
2. Multiple synchronized tasks are called at different time periods
In jQuery's animation, we often write a continuous animation code
$book.animate({
opacity: 0.25,
}).animate({
opacity: 0.5
}).animate({
opacity: 1
})
The intuition is that after the end of the first animate, the element's opacity becomes 0.25, then the second animate continues, the element's opacity becomes 0.5, and so on. But in fact, there is a fundamental problem here. Animations are called asynchronously, and the animate method is executed synchronously, so it needs to be designed to the queue. jQuery also presents an queue method specially designed for animation
Queues are also a special kind of linear table. In JavaScript, we can implement such a design directly by using arrays. The push() method of the array can add elements to the end of the array, and the shift() method can delete the first element of the array.
function Queue() {
this.dataStore = [];
this.enqueue = enqueue;
this.dequeue = dequeue;
this.first = first;
this.end = end;
this.toString = toString;
this.empty = empty;
}
///////////////////////////
// enqueue() Method to add to the end of the queue 1 An element: //
///////////////////////////
function enqueue(element) {
this.dataStore.push(element);
}
/////////////////////////
// dequeue() Method to delete the header element: //
/////////////////////////
function dequeue() {
return this.dataStore.shift();
}
/////////////////////////
// You can read the elements at the head and end of the queue using the following method: //
/////////////////////////
function first() {
return this.dataStore[0];
}
function end() {
return this.dataStore[this.dataStore.length - 1];
}
/////////////////////////////
// toString() Method displays all the elements in the queue //
/////////////////////////////
function toString() {
var retStr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retStr += this.dataStore[i] + "\n";
}
return retStr;
}
////////////////////////
// Need to be 1 Five methods to determine whether the queue is empty //
////////////////////////
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(" Head of the queue : " + q.first()); //("Aaron1");
console.log(" Queue tail : " + q.end()); //("Aaron3");
Queue USES a linear storage, then order to store 1 exist some disadvantages, such as queuing to buy tickets, if the first buy, later will naturally move one space, this involves the entire queue every one member to move forward, but JavaScript queue array is used to describe, the underlying solve some disadvantages. Of course, there are also lookup algorithms, such as using arrays to implement a single linked list structure, and so on. We will only discuss javascript's queues here
Simulate jQuery, using queues to achieve 1 animation
<div id="div1" style="width:100px;height:50px;background:red;cursor:pointer;color:#fff;text-align:center;line-height:50px;"> Click on the </div>
(function($) {
window.$ = $;
})(function() {
var rquickExpr = /^(?:#([\w-]*))$/;
function aQuery(selector) {
return new aQuery.fn.init(selector);
}
/**
* animation
* @return {[type]} [description]
*/
var animation = function() {
var self = {};
var Queue = []; // The animation queue
var fireing = false // Animation lock
var first = true; // through add Interface trigger
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
// A concrete execution algorithm is wrapped
//css3
//setTimeout
element.style.webkitTransitionDuration = '2000ms';
element.style.webkitTransform = 'translate3d(' + width + 'px,0,0)';
// Monitor animation over
element.addEventListener('webkitTransitionEnd', function() {
func()
});
}
var _fire = function() {
// Add animation now triggering
if (!fireing) {
var onceRun = Queue.shift();
if (onceRun) {
fireing = true;
//next
onceRun(function() {
fireing = false;
_fire();
});
} else {
fireing = true;
}
}
}
return self = {
// Increase the queue
add: function(element, options) {
Queue.push(function(func) {
makeAnim(element, options, func);
});
// If you have 1 The queues immediately trigger the animation
if (first && Queue.length) {
first = false;
self.fire();
}
},
// The trigger
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');
// call
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;"> Click on the </div><script type="text/javascript">
(function($) {
window.$ = $;
})(function() {
var rquickExpr = /^(?:#([\w-]*))$/;
function aQuery(selector) {
return new aQuery.fn.init(selector);
}
/**
* animation
* @return {[type]} [description]
*/
var animation = function() {
var self = {};
var Queue = []; // The animation queue
var fireing = false // Animation lock
var first = true; // through add Interface trigger
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
// A concrete execution algorithm is wrapped
//css3
//setTimeout
element.style.webkitTransitionDuration = '2000ms';
element.style.webkitTransform = 'translate3d(' + width + 'px,0,0)';
// Monitor animation over
element.addEventListener('webkitTransitionEnd', function() {
func()
});
}
var _fire = function() {
// Add animation now triggering
if (!fireing) {
var onceRun = Queue.shift();
if (onceRun) {
fireing = true;
//next
onceRun(function() {
fireing = false;
_fire();
});
} else {
fireing = true;
}
}
}
return self = {
// Increase the queue
add: function(element, options) {
Queue.push(function(func) {
makeAnim(element, options, func);
});
// If you have 1 The queues immediately trigger the animation
if (first && Queue.length) {
first = false;
self.fire();
}
},
// The trigger
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');
// call
oDiv.onclick = function() {
$('#div1').run({
'width': '500'
}).run({
'width': '300'
}).run({
'width': '1000'
});
};
</script>