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>


Related articles: