onload Functions Firing Out Of Order - javascript

Any idea why the following code:
<script>
var access_token;
var access_token_secret;
function Login(){
img = document.getElementById('authenticate');
img.src = 'authenticate.png';
login = document.getElementById('login');
login.style.visibility="visible";
}
function cookieHandlerStep1(){
chrome.cookies.get({
url:URL_GOES_HERE,
name:'access_token'
},
function(cookie){
if(cookie){
access_token = cookie['value'];
cookieHandlerStep2();
} else{
Login();
}
});
}
function cookieHandlerStep2(){
chrome.cookies.get({
url:URL_GOES_HERE,
name:'access_token_secret'
},
function(cookie){
if(cookie){
access_token_secret = cookie['value'];
Interact();
} else{
Login();
}
});
}
function Interact(){
alert(access_token);
xhr = new XMLHttpRequest();
xhr.open("GET", URL_GOES_HERE, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
document.write(xhr.responseText);
}
}
xhr.send();
}
</script>
<body onload="cookieHandlerStep1(),cookieHandlerStep2(),Interact()">
Could possibly have the functions executing out of sequence?

They're not firing out of order. You've provided callbacks to chrome.cookies.get which are not guaranteed to be called before the rest of the code. The first function returns before the callbacks are fired, and the next two (cookieHandlerStep2() and Interact()) get called.
However, in these callbacks, cookieHandlerStep1() is already calling cookieHandlerStep2() which then calls Interact() - so I presume what you actually want in your onload is just the first function to initiate the chain:
<body onload="cookieHandlerStep1()">

Related

A JavaScript function is repeated many times

I have two function print and callPrint bellow. I click call function print the first time is right.
But when click call function print the second or third then function callPrint will be call 2 times or 3 times.
I have debug on attack file.
function print(url) {
console.log('print');
var _this = this, iframeId = 'iframeprint', $iframe = $('iframe#iframeprint');
if ($iframe.attr('src') != url) {
$.when(
$iframe.attr('src', 'about:blank'),
$iframe.load(function () {
console.log($iframe.prop('contentWindow').document.readyState);
})
).done(function () {
$iframe.attr('src', url);
$iframe.load(function () {
console.log('new');
_this.callPrint(iframeId);
});
});
} else {
console.log('old');
_this.callPrint(iframeId);
}
}
// initiates print once content has been loaded into iframe
function callPrint(iframeId) {
console.log('callPrint');
$('div.wait').hide();
var PDF = document.getElementById(iframeId);
PDF.focus();
PDF.contentWindow.print();
return false;
}
A JavaScript function is repeated many times
The problem is because you're attaching two new load() event handlers to the iframe every time print() is called. To fix this, add a single load() event handler and call your function from in there. This will be triggered whenever you update the src attribute on the element. Try this:
var $iframe = $('#iframeprint').load(function() {
// You'll need to make sure the function is in scope of the handler
// There's not enough information in the OP for me to show you how
callPrint('iframeprint');
});
function print(url) {
var _this = this;
if ($iframe.attr('src') != url) {
$iframe.attr('src', url);
} else {
_this.callPrint(iframeId);
}
}
Thanks "Rory McCrossan". I add setTimeout function when callPrint so dialog print will open. But I can't vote for you at the moment.
var $iframe = $('iframe#iframeprint').load(function () {
// You'll need to make sure the function is in scope of the handler
// There's not enough information in the OP for me to show you how
setTimeout(function () {
callPrint('iframeprint');
}, 100);
});
function print(url) {
if ($iframe.attr('src') != url) {
$iframe.attr('src', url);
} else {
console.log('old');
callPrint('iframeprint');
}
}
// initiates print once content has been loaded into iframe
function callPrint(iframeId) {
$('div.wait').hide();
var PDF = document.getElementById(iframeId);
PDF.focus();
PDF.contentWindow.print();
}

Event Handler to run only when previous event handling is complete

Attached Event handler to callback like :
$("someSelector").on('click',callBackHandler);
function callBackHandler(){
//Some code
$.ajax({
//Ajax call with success methods
})
}
My success method is manipulating some object properties. Since ajax is involved, it will not wait for the completion and next event handling will start. How can I make sure next click event handling starts only when previous handling is done.
Cannot think of a way of using deferred manually on this because I am triggering event manually on base of some condition in for loop (Not a clean style of coding, but has no other option in particular use case).
$('someSelector').trigger('click');
$("someSelector").on('click', function(event) {
event.preventDefault();
var urAjax = $.ajax({
// Ajax Call here...
});
urAjax.always(function(response) {
$.when( callBackHandler() ).done(function() {
// Handle your ajax response in here!
});
});
});
function callBackHandler() {
// Do Stuff
}
callBackHandler function will fire, and when it's done, your ajax response for .always will fire directly after that. This allows for your ajax to load while the callBackHandler function is running also, but doesn't fire the response until after the function is done! Hopefully I'm understanding what you are asking for here.
You can see an example jsfiddle located here: https://jsfiddle.net/e39oyk8q/11/
Try clicking the submit button multiple times before the AJAX request is finished, you will notice that it will loop over and over again the total amount of clicks you give it on the Submit button. You can see this by the amount of times the Alert box pops up, and also, it adds 100 to the len (that gets outputted on the page) during each call to the callBackHandler function. So, I do believe this is what you asked for.
And, ofcourse, you can still use: $('someSelector').trigger('click');
EDIT
Another approach is to return a json object that can be used within the ajax call or wherever you need it within the click event, like so:
$("someSelector").on('click', function(event) {
event.preventDefault();
var myfunc = callBackHandler();
var urAjax = $.ajax({
type: 'POST',
url: myfunc['url'],
data: myfunc['data']
});
urAjax.always(function(response) {
$.when( myfunc ).done(function() {
console.log(myfunc['time']);
// Handle your ajax response in here!
});
});
});
function callBackHandler() {
var timestamp = new Date().getTime();
return { url: 'my_ajax_post_url', data: {data1: 'testing', data2: 'testing2'}, time: timestamp }
}
fiddle example here: https://jsfiddle.net/e39oyk8q/15/
You can remove the binding on the call of function and bind again when the ajax is done().
function callBackHandler(){
$("someSelector").off('click');
//Some code
$.ajax({
//Ajax call with success methods
}).done(function(){
$("someSelector").on('click',callBackHandler);
})
}
var requestDataButton = document.querySelector('.js-request-data');
var displayDataBox = document.querySelector('.js-display-data');
var displayOperationsBox = document.querySelector('.js-display-operations');
var displayNumberOfRequestsToDo = document.querySelector('.js-display-number-of-requests-to-do');
var isAjaxCallInProgress = false;
var numberOfAjaxRequestsToDo = 0;
var requestUrl = 'http://jsonplaceholder.typicode.com/photos';
requestDataButton.addEventListener('click', handleClick);
function handleClick() {
displayNumberOfRequestsToDo.innerText = numberOfAjaxRequestsToDo;
numberOfAjaxRequestsToDo++;
if(!isAjaxCallInProgress) {
isAjaxCallInProgress = true;
requestData();
}
}
function handleResponse(data) {
displayData(data);
displayOperationsBox.innerHTML = displayOperationsBox.innerHTML + 'request handled <br>';
numberOfAjaxRequestsToDo--;
displayNumberOfRequestsToDo.innerText = numberOfAjaxRequestsToDo;
if(numberOfAjaxRequestsToDo) {
requestData();
} else {
isAjaxCallInProgress = false;
}
}
function displayData(data) {
displayDataBox.textContent = displayDataBox.textContent + JSON.stringify(data[0]);
}
function requestData() {
var request = new XMLHttpRequest();
request.open('GET', requestUrl, true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.response);
handleResponse(data);
} else {
// on error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
displayOperationsBox.innerHTML = displayOperationsBox.innerHTML + 'request sent <br>';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="js-request-data">Request Data</button>
<div>
<h2>Requests wainting in a queue to be sent:
<span class="js-display-number-of-requests-to-do">
0
</span>
</h2>
</div>
<div>
<h2>Operations:</h2>
<div class="js-display-operations"></div>
</div>
<div>
<h2>Response Data:</h2>
<div class="js-display-data"></div>
</div>
edit
here's a utility function that takes similar arguments as $.ajax, and then returns an augmented $.ajax function that keeps an eye on its previous calls and waits for all preceding requests to finish before dispatching another ajax call (are fired sequentially):
function sequentialize(requestData, responseHandler) {
let inProgress = false;
let deferredRequests = 0;
const makeRequest = () => {
$.ajax(requestData).then(processManager);
};
const processManager = (data) => {
responseHandler(data);
if (deferredRequests) {
deferredRequests--;
makeRequest();
} else {
inProgress = false;
}
};
return function () {
if (!inProgress) {
inProgress = true;
makeRequest();
} else {
deferredRequests++;
}
};
}

Timing on GET info from PHP/SQL

Just for you to know I'm less than a newbie!
I have the following javascript code:
window.onload = function() {
renderTime();
getsec(myHandler);
countdown('countdown');
...
}
function myHandler(resultado) {
seconds = resultado;
}
function reqListener () {
console.log(this.responseText);
}
function getsec(callback) {
var indice = 1;
var oReq = new XMLHttpRequest();
oReq.onload = function() {
var variarr = JSON.parse(this.responseText);
callback(variarr[0]);
};
oReq.open("GET", "getsec.php?lei="+indice, true);
oReq.send();
}
This works perfectly for me. The intention is to get data from MySQL table through getsec.php every second. As you can see I have function countdown('countdown') that looks like this:
function countdown(element) {
...
interval = setInterval(function() {
...
if( runned == false){ // This condition happens
...
} else {
...
}
}, 1000);
}
I tryed to put function getsec(myHandler) inside function countdown('countdown')
if( runned == false){ // This condition happens
getsec(myHandler);
and I stop getting the information I want.
Can anyone explain me why?

Javascript setTimeout and Chrome Workers, I don't get it

I have the following files: (inc.js is included in my html page)
inc.js
var field = new Worker('ajax.js');
field.addEventListener('message', function(e) {
var data = JSON.parse(e.data);
document.getElementById('fieldToUpdate').innerHTML = data[0];
}, false);
field.postMessage(0);
ajax.js
var xhr = new XMLHttpRequest();
function getData() {
xhr.open('get', 'field.php');
xhr.onreadystatechange = processData;
xhr.send(null);
}
function processData() {
if (xhr.readyState == 4) {
self.postMessage(xhr.responseText);
setTimeout(getData, 5000);
}
}
onmessage = function() {
setTimeout(getData, 5000);
}
My Problem is now, that this Script doesn't make one http request each 5 seconds but it starts as soon as one is finished.

Stop html submit button in js ajax function

I want to stop the submit button in the js function checkUni()
Usually in js you can just return false, but that it not gonna work in my case because its an asynchronous (ajax)function, so the outer function will return before the inner function is able to determine wether to return false or true.
Here is the js function:
function checkUni() {
var URL = "http://localhost:8080/GradSchoolApp/test.jsp";
var container = document.getElementById("container_ID"); //destination of returned data
var request = false;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
}
}
}
request.open("GET", URL, true);
request.onreadystatechange = function() {
if (request.readyState == 4) {
//SOME CODE
//IF <something> then STOP SUBMIT BUTTON
container.innerHTML = request.responseText;
}
}
request.send(null);
}
Simply return false in the onclick listener.
<input type="submit" onclick="checkUni(); return false;"/>
You can set the action of the form element to "#" which will have the same effect.

Categories