When are IndexedDB operations executed? [duplicate] - javascript

While reading the HTML5 IndexedDB Specification I had some doubts about its asynchronous request model. When looking at the request api example, the open method is used to start an async request.
var request = indexedDB.open('AddressBook', 'Address Book');
request.onsuccess = function(evt) {...};
request.onerror = function(evt) {...};
At the time this request is started, there are no event handlers defined yet.
Isn't this a race condition?
What happens when the open method succeeds before the javascript interpreter executes the assignment to onsuccess?
Or is the request only really started once both callbacks are registered?
In my opinion an api like the following would be much more logical:
db.open('AddressBook', 'Address Book', {
onsuccess: function(e) { ... },
onerror : function(e) { ... }
});

There will be no race condition because JavaScript engine will finish executing actual scope (function) and then fire any callback or event handler. Read following comment on Mozilla Hacks.

Related

Multiple HTTP Client Requests not storing session data

I have an issue and i wonder is it possible that the code is to fast that its creating separate session ids, let me elaborate. I have two separate HTTP Clients that perform one after each other (see code below). The strange issue i have is in the second HTTP client request all i am doing is retrieving some session data. However sometimes it returns the data fine and other times the session info is undefined, which is causing no end of problems. Once i remove the second Http client the issue no longer occurs.
A bit of research i think it could be down to asynchronous client, could i re-use the same Http client variable for the next operation and session data will be kept? Any suggests or knowledge would be much appreciated.
this.login = function(username, password, loaded, failed, incorrect) {
var xhr = Ti.Network.createHTTPClient({
onload : function(e) {
var response = this.responseText;
switch(response) {
case "1":
loaded();
break;
case "0":
incorrect();
break;
case "2":
incorrect();
break;
case "3":
incorrect();
break;
default:
failed();
}
},
onerror : function(e) {
failed(e);
},
timeout : 5000,
validatesSecureCertificate : false
});
xhr.open('POST', this.url, true);
xhr.send({
'action' : 'login',
'email' : username,
'password' : password,
});
var getdb = Ti.Network.createHTTPClient({
onload : function(e) {
var response = this.responseText;
Ti.App.Properties.setString('name', response);
},
onerror : function(e) {
failed(e);
},
timeout : 5000,
validatesSecureCertificate : false
});
getdb.open('POST', this.url, true);
getdb.send({
'action' : 'get_name',
'device' : 'mobile'
});
};
Your problem is the fact that you're executing both calls at the same time. So the order of execution is unknown. What you need to do is call the 2nd after the first has finished. For this to work you will need to add the second http call within the callback of the first.
And to make your code more organised I recommend using functions! Makes it also more readable.
function doBothCalls(){
doFirstCallFunction(function(){
doSecondCallFunction();
}
}
The doFirstCallFunction then gets a callback function, this callback function you should call after the first one has gotten into the http callback.
What you need here is called Promises in Javascript.
When you do async calls, they all happen in random order of time , so you cannot do a async call which depends on result of another async call in same execution context(which you are doing in your code)
To overcome this, Javascript has functionality for promises which in nutshell means:
A Promise object represents a value that may not be available yet, but will be resolved at some point in the future. It allows you to write asynchronous code in a more synchronous fashion. For example, if you use the promise API to make an asynchronous call to a remote web service you will create a Promise object which represents the data that will be returned by the web service in future.

Trouble with callback function in asynchronous 'Post'

I am new to javascript, and I am having an issue with a line of code executing before the previous line has finished. From what I understand, I need to create a callback function which will make the last line wait for the previous line to finish. My program takes user input and uses an asynchronous 'post' to send it to a website, and then a message is returned. My original problem occurred when I had the two following lines of code together:
req.send(JSON.stringify(payload))
event.preventDefault();
preventDefault() is not waiting for the send() function to finish. I have tried implementing a callback function, but I am having problems with that as well.
function sendReq(callback){
req.send(JSON.stringify(payload), function(){
callback();
});
}
sendReq(function(){
event.preventDefault();
});
Any suggestions would be much appreciated. Here is my entire code in case that helps.
var apiKey = "appid=fa7d80c48643dfadde2cced1b1be6ca1";
document.addEventListener('DOMContentLoaded', bindButtons);
function bindButtons(){
document.getElementById('dataSubmit').addEventListener('click', function(event){
var req = new XMLHttpRequest();
var payload = {longUrl:null};
payload.longUrl = document.getElementById('inputData').value;
req.open('POST', 'http://httpbin.org/post&' + apiKey, true);
req.setRequestHeader('Content-Type', 'application/json');
var response = JSON.parse(req.responseText);
req.addEventListener('load',function(){
if(req.status >= 200 && req.status < 400){
document.getElementById('outputData').textContent = response.longUrl;
}
else
console.log("Error in network request");
});
function sendReq(callback){
req.send(JSON.stringify(payload), function(){
callback();
});
}
sendReq(function(){
event.preventDefault();
});
});
}
You misunderstand how callbacks work. Check out this article from recurial.com: Understanding callback functions in Javascript
You can't "wait" in JavaScript[*] - due to something called "Run-to-completion" semantics: your code always runs in response to an event (such as "DOMContentLoaded", "click", or XHR's "load") and no more events - and no other event handlers - will be processed until your currently running code finishes (typically by return-ing from the outermost function -- the event handler).
Long-running JS code makes the web page freeze, which is why you were asked to write an asynchronous request in the first place -- synchronous XHR will cause the page to freeze while your code waits for the response from the server.
To avoid the freezes and still get the job done, you can structure your code as a series of callbacks: after you start an asynchronous request you return from the current function and let the system call you back when it has the response. The only moment when you can use the response is in the callback, by the very definition of the callback.
In your case, the callback that indicates that the response is available is the load handler. That's where you should move your var response = JSON.parse(req.responseText); line.
PS. preventDefault() is completely unrelated to your situation, it can't be used to "wait for the send() function to finish"; it's used in cases when you handle an event (such as onsubmit for a <form>) and you want to prevent something that the browser does by default when this event fires (in the <form> example -- well -- submitting the form).
PPS. After you figure out the basics and start writing code that has more than 2 callbacks in a row, look up "promises".
PPPS. [*] Ignore this remark, I added it just to be precise, as it will only confuse you at this stage: You can't "wait" in JavaScript unless you're writing a "generator" and/or using the currently unavailable async/await).

Synchronous XMLHttpRequest in WebApi 2

I have a webApi 2 application. I used Ajax several time in this way async:false , because sometimes
The statement I am calling has to be complete before the next statement in my function can be called
I get a browser warning then
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
I understand that calling a web service synchronisly can make problems such as a long waiting, browser crush ... etc. But I need to get the result before continuing the next statement.
I need to know
How can I avoid this warning and amke the call asynchrous?
Why Synchronous XMLHttpRequest on the main thread is deprecated? what is the meaning of this statement?
You could move your sync call to a web worker. But again, you will make it async.
Its better to make the current sync call to server as async call.
Example(pseudo sync call code):
var dataFromServer = makeSyncCallToServer();
//use dataFromServer
Example(pseudo async call code):
makeAsyncCallToServer(function(dataFromServer) {
//use dataFromServer here
});
If you want to make multiple calls to server, then async comes handy here.
For example, you could use async.series
async.series([yourAsnycFunctionOne, yourAsnycFunctionTwo, yourAsnycFunctionThree], finalFunctionToCall)
So yourAsnycFunctionOne, yourAsnycFunctionTwo, yourAsnycFunctionThree will be called in series and finalFunctionToCall will be called in the end of the series.
In your case, you could do something like:
function getCustomerList(callback) {
//make the async http call and call "callback" with the customer data
}
function postFormDataToServer(formdata, callback) {
//send form data server and call "callback" after successful post
}
function hideGrid() {}
function hideForm() {}
function showForm() {}
function showGrid() {}
$('#add-button').on('click', function() {
showForm();
hideGrid();
});
$('#form-id').on('submit', function(e) {
e.preventDefault();
var formdata = {/**populate form data**/};
hideForm();
postFormDataToServer(formdata, function() {
getCustomerList(function(customerList) {
//populate grid with new data
showGrid();
});
});
});

Performance of Javascript Function that makes HTTP Request

I need a way of measuring the response time of a javascript function that creates an http request, that includes the response time of that http request. I do not have access to modify that funciton however.
Here's what I'm trying to do:
var startTime = performance.now(); //log start timestamp
foo.bar(); //The Function that generates an HTTP request
var endTime = performance.now(); //log end timestamp
var diffTime = endTime - startTime;
but that only captures the time it takes for the function to generate the request. Is there a way to capture the response time of the request that gets genearated in javascript?
You have to check the timestamp inside of the request callback.
EDIT:
If you want do measure this completely independently from the application (so just by adding another js file), I guess you can decorate XMLHttpRequest.
window.XMLHttpRequest = function () {...}
Your wrapper will need to have the same API, so that the app still works, and can also measure performance internally.
I would usually just hit F12 to bring up dev tools on any browser, go to the network tab, and look at the ajax call that is being made, that will tell you exactly how long the request and repose took with very fine grained details.
However, if you are looking to factor in the java-script that makes the ajax call then start your timer right before the call and stop it on the complete event of the ajax call (will require editing the function). that is the only way to catch it if it is asynchronous. And just guessing here based on your description that it is actually an async call, and that explains the behavior of the function just making the ajax call then returning - and not caring about the status or the response...
If you happen to be using jQuery in your inaccessible function, you can give this a shot:
$.when(foo.bar()).done(function()
{
console.log("Fired after ajax request is done!");
});
Take a look also at:
var obj = {
promise: function() {
// do something
}
};
$.when( obj ).done( fn );
or
var obj = {
promise: foo.bar()
};
$.when( obj ).done( callback );
or check out this great article http://www.erichynds.com/blog/using-deferreds-in-jquery
well, if you don't have an acces to the function or you can't edit the ajax call, you can create a listener. the strategy:
declare a flag befor the http request call
start the call
start a listener that loop every X mili-seconds and check for a finish status (outside the ajax function and after it is called)
you should ask yourself: which kind of variables are changed when this call is over? event a visual change on the ui can be used as a flag
and if you wonder how to create your listener.. it looks something like this:
function listener()
{
// do some checks here
if (done)
{
var endTime = performance.now(); //log end timestamp
var diffTime = endTime - startTime;
}
else
{
setTimeout(listener(), 100);
}
}
listener(); // activate the listener

what is the right way to manage multiple ajax requests?

We've all seen some examples in AJAX tutorials where some data is sent. They all (more or less) look like:
var http = createRequestObject(); // shared between printResult() and doAjax()
function createRequestObject() { /* if FF/Safari/Chrome/IE ... */ ... }
function printResult()
{
if (http.readyState == 4) { ... }
}
function doAjax() {
var request = 'SomeURL';
http.open('post', request);
http.onreadystatechange = printResult;
data = ...; // fill in the data
http.send(data);
}
// trigger doAjax() from HTML code, by pressing some button
Here is the scenario I don't understand completely: what if the button is being pressed several times very fast? Should doAjax() somehow re-initialize the http object? And if if the object is re-initialized, what happens with the requests that are being already on air?
PS: to moderator: this question is probably more community-wiki related. As stated here (https://meta.stackexchange.com/questions/67581/community-wiki-checkbox-missing-in-action) - if I've got it right - please mark this question appropriately.
Since AJAX has asynchronus nature, with each button click you would raise async event that would GET/POST some data FROM/TO server. You provide one callback, so it would be triggered as many times as server finishes processing data.
It is normal behaviour by default, you should not reinitialize of http object. If you want to present multiple send operation you have to do that manually (e.g. disabling button as first call being made).
I also suggest to use jQuery $.ajax because it incapsulate many of these details.
Sure that numerous libraries exist nowadays that perform a decent job and should be used in production environment. However, my question was about the under-the-hood details. So here I've found the lamda-calculus-like way to have dedicated request objects per request. Those object will obviously be passed to the callback function which is called when response arrives etc:
function printResult(http) {
if (http.readyState == 4) { ... }
...
}
function doAjax() {
var http = createRequestObject();
var request = 'SomeURL';
http.open('get', request);
http.onreadystatechange = function() { printResult(http); };
http.send(null);
return false;
}
Successfully tested under Chrome and IE9.
I've used a per-page request queue to deal with this scenario (to suppress duplicate requests and to ensure the sequential order of requests), but there may be a more standardized solution.
Since this is not provided by default, you would need to implement it in JavaScript within your page (or a linked script). Instead of starting an Ajax request, clicking a button would add a request to a queue. If the queue is empty, execute the Ajax request, with a callback that removes the queued entry and executes the next (if any).
See also: How to implement an ajax request queue using jQuery

Categories

Resources