Created
October 21, 2013 07:43
-
-
Save dzenkovich/7080013 to your computer and use it in GitHub Desktop.
JS Core: Task 5. Requests Queue.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This self-invoking anonymous function consists of: | |
* - onload finction, which cotains functions that are responsible for the logic of click event handling on the Switch button | |
* - the helper function for adding event listeners; | |
* - the RequestsQueue constructor: impelements the dymanic queue | |
* | |
* It encloses variables and functions in it's scope and helps us keep them out of Global | |
* This is the most simple scenario of Module pattern. | |
* | |
* Working process: by clicking the button on the page, the requests start generating. The amount of requests in the bunch is a random number (from 1 to 3). | |
* The requests go into the queue until the Stop button is clicked. | |
* To return SUCCESSFUL responses the folder with the files should be placed on the server | |
*/ | |
(function(){ | |
/** | |
* Helper function to create event listeners | |
* @param element - DOM object that is the event target | |
* @param event - a string representing the event type to listen for | |
* @param func - the event listener function that is called when the event occurs | |
*/ | |
function addEvents(element, event, func){ | |
if(element.addEventListener) | |
{ | |
element.addEventListener(event, func, false); | |
} | |
else if(element.attachEvent) | |
{ | |
element.attachEvent('on' + event, func); //IE browser | |
} | |
} | |
/** | |
* Constructor function which describes the queue and its working process of adding/removing requests | |
* @constructor | |
*/ | |
function RequestsQueue () { | |
var self = this, //this variable is created to use the RequestsQueue object reference in the inner function | |
url = 'response.json', | |
queueElementsList = [], //the array which contains the incoming requests | |
states = { | |
free: 'free', | |
busy: 'busy' | |
}, | |
queueState = states.free, // default state of the queue, when the page is loaded | |
resultBox = document.createElement('div'), // the DOM element which contains the results of the requests and responses | |
currentListItem; | |
/** | |
* Checks the ready state of the response and returns the function which include 2 other functions of processing the responses. | |
* _processSingleResponse - function that prepares the results for one response | |
* _processBunchResponse - function that prepares the results for the whole bunch | |
* @param arrXhr - the array of XHR requests | |
* @param index - the sequence number of the processing request in the array | |
* @returns {Function} | |
* @private | |
*/ | |
function _processResponse(arrXhr, index) { | |
return function() { | |
if(arrXhr[index].readyState === 4) { //checks if the request object doesn't exist or if it ready state is not equal to 4 (4 means that the request finished and response is ready) | |
//processing for one request | |
_processSingleResponse(arrXhr, index); | |
// processing if all xhr's are completed | |
_processBunchResponse(arrXhr); | |
} | |
} | |
} | |
/** Creates AJAX requests | |
* Sends requests for the processing | |
* @private | |
*/ | |
function _sendRequestBunch() { | |
var xhrArray = [], // the array for the requsts | |
requestsAmount = queueElementsList[0]; //takes the value always from the 1st element with the index 0 from "queueElementsList" variable as a queue is a First-In-First-Out (FIFO) data structure | |
//creates the LI element, appends it to the OL element and writes the information of the amount of requsts | |
currentListItem = document.createElement('li'); | |
resultBox.getElementsByTagName('ol')[0].appendChild(currentListItem); | |
currentListItem.innerHTML = 'Requests amount: ' + requestsAmount + '<br/>'; | |
for(var i = 0; i < requestsAmount; i++) { | |
xhrArray[i] = new XMLHttpRequest(); //the XMLHttpRequest object is used to exchange data with a server without having to do a full page refresh | |
xhrArray[i].open('POST', url, true); //specifies the type of request (POST/GET), the URL, and if the request should be handled asynchronously or not | |
xhrArray[i].onreadystatechange = _processResponse(xhrArray, i); //stores a function which is called automatically each time the readyState property changes (it changes from 0 to 4) | |
xhrArray[i].send(null); //sends the request to the server, null means that no parameters are sending to the server | |
} | |
} | |
/** | |
* Processes one response and writes the result to the DOM element | |
* @param arrXhr - the array of XHR requests | |
* @param arrIndex - the sequence number of the processing request in the array | |
* @private | |
*/ | |
function _processSingleResponse(arrXhr, arrIndex) { | |
var statusText, | |
spanElement; | |
if (arrXhr[arrIndex].status === 200) { //checks if the status is success (status is 200 for a successful request) | |
statusText = 'Single response status: 200 <br/>'; | |
} | |
else {// if response failed | |
statusText = 'Single response status: NOT 200 <br/>'; | |
} | |
spanElement = document.createElement('span'); | |
spanElement.innerHTML = statusText; | |
currentListItem.appendChild(spanElement); | |
} | |
/** | |
* Processes a bunch of responses and writes the result to the DOM element | |
* @param arrXhr - the array of XHR requests | |
* @private | |
*/ | |
function _processBunchResponse(arrXhr) { | |
var isAllComplete = true, // boolean variable which shows if all requests are completed | |
isAllCompleteSucc = true, // boolean variable which show if all requests are successful | |
requestsAmountInBunch = arrXhr.length, // the amount of requests in the bunch | |
statusText, spanElement; | |
//loops through the items in the array | |
for (var i = 0; i < requestsAmountInBunch; i++) { | |
if( (!arrXhr[i]) || (arrXhr[i].readyState !== 4)) { //checks if the request object doesn't exist or if it ready state is not equal to 4 (4 means that the request finished and response is ready) | |
isAllComplete=false; | |
break; //breaks the loop and continues executing the code after the loop | |
} | |
} | |
if(isAllComplete) { | |
for(var i = 0; i < requestsAmountInBunch; i++) { | |
if(arrXhr[i].status !== 200) { //checks the status of a request | |
isAllCompleteSucc = false; | |
break; | |
} | |
} | |
queueElementsList.shift(); //removes the first item of the array | |
queueState = states.free; //sets the status of the queue to free | |
//sets the status of the bunch of requests | |
if(isAllCompleteSucc) { | |
statusText = 'All SUCCESS'; | |
} | |
else { | |
statusText = 'All not SUCCESS'; | |
} | |
spanElement = document.createElement('span'); | |
spanElement.innerHTML = statusText; | |
currentListItem.appendChild(spanElement); | |
//if the queue is free and not empty it continues sending requests for processing | |
if ((queueState === states.free) && (queueElementsList.length)) { | |
queueState = states.busy; | |
_sendRequestBunch(); | |
} | |
} | |
} | |
/** | |
* Runs on creating a new object | |
* @private | |
*/ | |
function _create() { | |
resultBox.className = 'result'; //adds class name to the DOM element for results of requests | |
resultBox.appendChild(document.createElement('ol')); // creates element ol and inserts it into the result box | |
document.body.appendChild(resultBox); // appends the result box to the body element | |
} | |
/** | |
* Adds a new element to the array of requests, checks the state of the queue and if the queue is free and not empty it sends the request (bunch of requests) for the processing | |
* @param amount - the amount of the AJAX requests | |
*/ | |
this.addToQueue = function(amount) { | |
queueElementsList.push(amount); //adds a new request to the array | |
if ((queueState === states.free) && (queueElementsList.length)) { //checks if the queue is not processing anything and if the queue contains elements | |
queueState = states.busy; //changes the state of the queue from free to busy | |
_sendRequestBunch(); //sends the request/request bunch for processing | |
} | |
} | |
_create(); | |
} | |
/** | |
* Runs when the DOM is loaded | |
*/ | |
function onload() { | |
var switchButton = document.getElementById('switchButton'), //gets the button element from the DOM, this button switches the queue entry of requests | |
buttonText = { | |
start: 'START sending requests', | |
stop: 'STOP sending requests' | |
}, | |
intervalId, // unique interval ID | |
intervalTime = 2000, // interval of adding requests to the queue | |
maxRequestsNumber = 3, // max amount of requests in a bunch | |
queue = new RequestsQueue(); //creats a new queue object | |
switchButton.setAttribute('data-switch', 'start'); //sets data-switch attribute to the 'start' value as when the page is loaded only "start" action may be done | |
switchButton.innerHTML = buttonText.start; //sets text for the switch button | |
/** | |
* Starts sending requests to the queue | |
*/ | |
function startRequests(){ | |
var requestsNumber; | |
intervalId = setInterval(function(){ //initializes the interval for adding requests to the queue | |
requestsNumber = Math.floor((Math.random()*maxRequestsNumber) + 1); //gets the random integer number from 1 to the value of max amount of requests | |
queue.addToQueue(requestsNumber);// adds the requests to the queue | |
}, intervalTime); | |
} | |
/** | |
* Stops sending requests to the queue | |
*/ | |
function stopRequests() { | |
clearInterval(intervalId); //cancels repeated adding of requests to the queue | |
} | |
/** | |
* Toggles the state of the switch button | |
*/ | |
function toggleButton () { | |
if (switchButton.getAttribute('data-switch') === 'start') { | |
startRequests(); //start sending requests | |
switchButton.setAttribute('data-switch', 'stop'); | |
switchButton.innerHTML = buttonText.stop; | |
} | |
else { | |
stopRequests(); //stop sending requests | |
switchButton.setAttribute('data-switch', 'start'); | |
switchButton.innerHTML = buttonText.start; | |
} | |
} | |
addEvents(switchButton, 'click', toggleButton); | |
} | |
addEvents(window, 'load', onload); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment