Delay script until all messages have been passed? - javascript

As usual, I have Googled this a fair bit and read up on the Message Passing API, but, again, I've had to resort to the good fellas at StackOverflow.
My question is this: When passing messages between a Google Chrome extension's background page and content script, is there any way to make it asynchronous - that is, to delay the JavaScript until the messages are detected as being successfully being passed?
I have a function immediately after the message-passing function makes use of the localStorage data that is passed. On first runs the script always results in an error, due to the data not being passed fast enough.
Currently, I'm circumventing this with setTimeout(nextFunction, 250); but that's hardly an elegant or practical solution, as the amount and size of the values passed is always going to change and I have no way of knowing how long it needs to pass the values. Plus, I would imagine, that passing times are relative to the browser version and the user's system.
In short, I need it to be dynamic.
I have considered something like
function passMessages(){
chrome.extension.sendRequest({method: "methodName"}, function(response) {
localStorage["lsName"] = response.data;
});
checkPassedMessages();
}
function checkPassedMessages(){
if (!localStorage["lsName"]){
setTimeout(checkPassedMessages, 100); //Recheck until data exists
} else {
continueOn();
}
}
but I need to pass quite a lot of data (at least 20 values) and, frankly, it's not practical to !localStorage["lsName1"] && !localStorage["lsName2"] etc etc. Plus I don't even know if that would work or not.
Does anyone have any ideas?
Thanks
Update: Still no answer, unfortunately. Can anyone offer any help at all? :/

I don't know whether I'm interpreting your question wrong. As far as I understand you are sending request from your extension page to a content script. The request handler in the content handler does some operation on the message passed after which you need the control back in the extension page. If this is what you need you have everything in the Google Extension Documentation. The following code works
//Passing the message
function passMessages(){
chrome.extension.sendRequest({method: "methodName"}, function(response) {
//callback function that will be called from the receiving end
continueOn();
});
}
//Recieving the message
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
//Do the required operation with the message passed and call sendResponse
sendResponse();
});

You can solve the general (ie, on any platform where you are communicating between distinct threads of execution) case of this problem by collecting the information passed, while waiting for some sort of following "go" message before you begin processing the collected information. You can use the same idea to have the sender wait for the complete reply.
Of course it's possible that your particular platform provides tools for doing this; but if not, you can always build the general solution by hand.

Related

Should I use try-catch when calling jquery plugin

So, I have jquery plugins (or any other plugins / functions / libraries, for what matters).
I was wondering if I should call the plugin inside a try-catch in order to avoid aty undefined type errors, which may possibly block the execution of the rest of the script.
This is how/where I call the plugins right now.
(function($){
$(document).ready(function(){
// jquery plugin
try {
$("#app").plugin();
} catch (e) {
console.log(e);
}
// some other function applied to entire document
try {
libraryFunction();
} catch (e) {
console.log(e);
}
});
})(jQuery);
I know this is not code review, but if you have any suggestions on how to improve this code, please let me know.
I have dealt with scenarios when a plugin error actually screwed the rest of the script and using try-catch to call the plugin solved the problem.
Using try-catch a lot may slow down your script, but unless you're dealing with long loops, the performance change will be unnoticeable.
It is always a good practice to handle unknown behavior with a try-catch block. But even more important is to know how to handle the exception once its caught. In the above code, the exception is only being logged(which is good) and nothing else. In that case your execution may still get blocked.
Additionally, it would be good to also throw the exception back to the caller and make it handle the behavior. For example, in the above code, if jquery threw an exception, you may let the caller know about the exception and the caller may decide to call the function again or do something else.
In short, after catching, handling decides how your execution will recover. Logging alone will not help.
Edit:
An example to show why an exception should be thrown back:
Lets say I have an AppThread that requests a worker thread to store some data in an SQL database. Such a code flow will ideally not require the worker thread to return anything to the caller because the Worker Thread simply executes some Insert statements.
Now, during the insertion, worker thread caught an SQLException and simply logged and returned. Now the app Thread was never notified of this exception and it simply assumes that the data was inserted as requested. After sometime, the AppThread now wants to read the same data from the Database and asks the WorkerThread to fetch it using some Id. This time, the code will not throw any exception and the result set will simply be null. Now remember, the AppThread was sure that the data would be present and will not know what to do if the result set is null. So in one way, the code execution gets blocked after sometime of the exception.
Now, had the Worker Thread notified the exception to the App Thread earlier, the AppThread would have been aware and would have reattempted the insert operation or would show a dialog to the user letting her/him know that the data may need to be verified before attempting insert again. Also as the exception was passed back, its message would give more hints of what went wrong to the user directly. He will not have to go back to the logs to check what went wrong.

How can I "ping" the user in JavaScript?

I need to get the request time it took the client to reach the server and the opposite.
And so I have been able to do this in Python which does not help me now on a webpage.
So I heard that it can be done using Ajax, is that true?
If so, Can you give me some details or information where I should start from?
Thank you, looking forward to a answer!
You could emulate a ping via http however that is not very accurate. A simple way would be to post the current timespamp in ms or ns and wait then for the response of the same time. The difference between the real time and time of the response is the so called round trip time (RTT). If you divide it by two you get the response time what the ping is.
On newer browsers, you can use the navigation timing API (HTML5 rocks article on navigation timing) to get a fine-grained break down of the time that it takes to load your page. You can simply subtract the relevant fields from "performance.timing" to get the timing that you are interested in. The (secureConnectionStart - connectStart) or (connectEnd - connectStart), depending on whether the connection is an SSL connection, looks like a reasonable approximation of ping time (though, as rekire# points out, you probably want to include more than just that if you are trying to measure the overall user-visible latency of your website for end users).
For your reference, the ajax ping works as below.
Unfortunately it is very possible you will get blocked by domain policy and never get a success.
function ping(){
$.ajax({
url: 'http://website.com',
success: function(result){
alert('replied');
},
error: function(result){
alert('error');
}
});
Please see this code as an example of a seemingly successful implementation for what you are trying to do.

Delay required in between the execution of two statements

i am working with extjs 4.2 and at one place i am loading the store object like this :
var userDetailStore = Ext.create('Ext.data.Store', {
model : 'Person.DetailsModel',
autoLoad : true,
proxy : {
type : 'ajax',
method : 'POST',
url : 'getValueAction.action',
reader : {
type : 'json',
root : 'details'
},
writer : {
type : 'json',
root : 'details'
}
},
fields : ['id','loginName','referenceId' ,'name']
});//Here I load the store which will definitely contain a list of values.
and in the very next line i want to get the referenceId of the first value from the store object like this
var empId = userDetailStore.getAt(0).get('referenceId')
and i am getting the error because till now the getCount() of the store object userDetailStore is giving me zero.But if i write an alert statement like alert('loading data'); before the line where i am getting the referenceId then the code works fine.The line userDetailStore.getCount() is giving me the exact value.
So i think some kind of delay is required between the loading the store and then using the store but I don't want an alert to show.I have even used the sleep() method in place of alert statement.But that is also not working.(BTW i don't even want to freeze the browser by executing the sleep())
Am i doing anything wrong while loading the store ?Is there any general way so that i will execute my code for using the store after the store is completely loaded ?
Somebody please help me out here...
Regards :
Dev
Vijay's answer is correct, but I thought I'd expand on the concept so that it's clear how this answer fits into what you're doing.
It's important to understand that when you make an AJAX request, the request is asynchronous. What this means in practical terms is that (as you found out) the remainder of your calling script does not wait for the asynchronous process to complete. Rather, the moment that you make an asynchronous request, your script is going to continue on it's merry way, executing the very next line of code.
So if you think about it, this makes perfect sense why you were not seeing a "count" in your store. While your async request was in the process of going to the server, getting the result, and then returning it to your request, the rest of your code kept right on executing, oblivious to what was happening in the async request (and this is precisely why async requests are powerful and awesome).
This is also why adding the alert seemed to "fix" your problem. When you call alert(), you literally halt execution of your script at the point of the alert. However, since your request for data was asynchronous, the time it took you to click the "OK" button of the alert (and hence resume processing of your script) gave the async request enough time to complete its lifecycle and update the original calling object.
In light of this, it's understandable why it would seem that a "delay" would be a desirable way to go, since the "delay" (or really, "halting") of the alert fixed your issue (at least on the surface). However, with async requests, you can never really know how long it's going to take to complete. If you have a large response, or there is unusual network latency, or any other number of issues...the hard-coded delay might work, but it also might not. Most maddening of all is that you'd never get consistent results, and would constantly be increasing the "delay" in order to accomodate all the things that could contribute to your async request taking longer and longer.
This is why the load() event of the store (and callbacks in general) is such a critical concept to understand and implement. By listening for the load() event, and then executing what code you need only within the context of that event firing, you can know for sure that the store's async request for data has completed.
If you've not used callbacks and event handling before, it does take a bit of getting used to in order to break out of the linear, procedural mindset. However, when dealing with AJAX requests in general, and event-driven frameworks like ExtJS 4 in particular, it's a concept you need to embrace in order to build effective and consistent applications.
use on load event to get the count after it's fully loaded
userDetailStore.on('load', function(){
alert("Fully loaded");
});
Here set autoload to false and on some action you can use load() to load your store.
store.load({
callback: function(records, operation, success) {
// do something after the load finishes
},
scope: this
});

how to silently guarantee executing an ASP.NET MVC3 action on page unload

I need to execute an action of a controller when a user leave a page (close, refresh, go to link, etc.). The action code is like:
public ActionResult WindowUnload(int token)
{
MyObjects[token].Dispose();
return Content("Disposed");
}
On window download I do Ajax request to the action:
$(window).unload(function ()
{
$.ajax({
type: "POST",
url: "#Url.Action("WindowUnload")",
data: {token: "#ViewData["Token"]"},
cache: false,
async: true
});
//alert("Disposing.");
})
The above ajax request does not come to my controller, i.e., the action is not executed.
To make the code above to work I have to uncomment the alert line, but I don't want to fire alert on a user.
If I change async option to false (alert is commented), then it sometimes works. For example, if I refresh the page several times too fast then the action will not be executed for every unload.
Any suggestions how to execute the action on every unload without alert?
Note, I don't need to return anything from action to the page.
Updated: answers summary
It is not possible reliably to do request on unload, since it is not proper or expected behavior on unload. So it is better to redesign the application and avoid doing HTTP request on window unload.
If it is not avoidable, then there are common solutions (described in the question):
Call ajax synchronously, i.e., async: false.
Pros: works in most cases.
Pros: silent
Cons: does not work in some cases, e.g, when a user refreshes the windows several times too fast (observed in Firefox)
Use alert on success or after ajax call
Pros: seems to work in all cases.
Cons: is not silent and fires pop up alert.
According to unload documentation, with async: false it should work as expected. However, this will always be a bit shaky - for example, user can leave your page by killing/crashing the browser and you will not receive any callback. Also, browser implementations vary. I fear you won't get any failproof even.
HTTP is stateless and you can never get a reliable way to detect that the user has left your page.
Suggested events:
Session timeout (if you are using sessions)
The application is going down
A timer (need to be combined with the previous suggestion)
Remove the previous token when a new page is visited.
Why does this need to happen at all?
From the code snippet you posted you are attempting to use this to dispose of objects server side? You are supposed to call Dispose to free up any un-managed resources your objects are using (such as Database connections).
This should be done during the processing of each request. There shouldn't be any un-managed resources awaiting a dispose when the client closes the browser window.
If this is the way you are attempting this in the manner noted above the code needs to be reworked.
Have you tried onbeforeunload()?
$(window).bind('beforeunload', function()
{
alert('unloading!');
}
);
or
window.onbeforeunload = function() {
alert('unloading!');
}
From the comment you made to #Frazzell's answer it sounds like you are trying to manage concurrency. So on the chance that this is the case here are two common method for managing it.
Optimistic concurrency
Optimistic concurrency adds a timestamp to the table. When the client edits the record the timestamp is included in the form. When they post their update the timestamp is also sent and the value is checked to make sure it is the most recent in the table. If it is, the update succeeds. If it is not then someone else got in sooner with an update so it is discarded. How you handle this is then up to you.
Pessimistic concurrency
If you often experience concurrency clashes then pessimistic concurrency may be better. Here when the client edits the record a flag is set on that row to lock it. This will remain until the client completes the edit and no other user can edit that row. This method avoids users loosing changes but add an administration over head to the application. Now you need a way to release unwanted locks. You also have to inform the user through the UI that a row is locked for edit.
In my experience it is best to start with optimistic concurrency. If I have lots of people reporting problems I will try to find out why people are having these conflicts. It maybe that I have to break down some entities in to smaller types as they have become responsible for doing too many jobs.
This wont work and even if you are able to somehow make it work it will give you lots of headaches later on, because this is not how the browser/HTTP is supposed to be used. When the page is unloading (in browser) the browser will call the unload event and then unload the page (you cannot make it wait, not even my making sync ajax calls) and in case the call was going on and the browser after executing the code unload the page, the call will also get cancelled and thats why you see the call on server sometimes and sometimes it doesn't work. If you could tell use why you want to do this we could suggest you a better approach.
You can't. The only thing you can do is prompt the user to stay and hope for the best. There are a whole host of security concerns here.

JQUERY or JS is there a way to detect anytime the Window is loading? Basically any network activity?

Is there a way with JQUERY or Javascript, to detect anytime the browser window is loading something, making an ajax call, loading an image, etc... Basically any network activity?
Something along the lines of this jQuery (put in the HEAD) should work.
var loading = true;
$(window).load(function () {
loading = false;
}).ajaxStart(function () {
loading = true;
}).ajaxComplete(function () {
loading = false;
});
Read up on ajaxStart for more details.
My answer below and the previous users' answers are only attempting to check if the browser is currently making an XmlHttpRequest (i.e. ajaxy) request.
You asked if you could tell if the browser was making any network request (i.e. downloading images/css or perhaps a long running 'comet' request). I don't know of any javascript API that would tell you this - they may exist but I suspect that if they do then they would be browser specific [if anyone out there knows the answer to this please chip in]. Obviously tools like Firebug and dynaTrace can detect network activity but I think these tool "hook in" to the browser a lot deeper down than javascript code.
Having said all that, if you want to count XHRs spawned by jQuery then dave1010's answer seems like a good one.
However I think it is prone to some race condition problems : -
According to the docs (http://api.jquery.com/ajaxStart/)
Whenever an Ajax request is about to be sent, jQuery checks whether there are any other outstanding Ajax requests. If none are in progress, jQuery triggers the ajaxStart event. Any and all handlers that have been registered with the .ajaxStart() method are executed at this time.
So if a long running XHR was started and another one was started before the first had completed, the ajaxStart handler would only be called once. The 2nd XHR could complete before the first one and set loading = false, even though the first request is still in progress.
Looking at the jQuery 1.4 source seems to confirm this. Interestingly, jQuery 1.4 has a count of active XHRs (jQuery.active) but this is not mentioned in the docs and so it is probably best not to use it (which is a pity because it would make life a bit easier).
See http://gist.github.com/277432#LID5052 for the code that checks to see that $.active is 0 before invoking ajaxStart handlers.
[I think] The 'ajaxSend' global event handlers are called before each and every XHR. Using this in preference to 'ajaxStart' should help but we will still need to keep a count of active requests as opposed to a simple "loading" flag.
Perhaps something like the following will work?
var activeXhrCount = 0;
$(document).ajaxSend(function() {activeXhrCount++;}).ajaxComplete(function(){activeXhrCount--;});
Be aware that this will give incorrect answers if any code calls $.ajax with the global option set to false and so is hardly bullet proof;
Also keep in mind that activeXhrCount only counts XHRs spawned by jQuery - those from other libraries that you may utilize will not be counted.
i think you have to build some think by your self,
i did something like this before [ like when gmail shows loading upper there ]
the idea is about making an array then add/remove from it and keep checking it for know if there is an open connection
the code should look like this
var liveAjax = [];
//making ajax call
liveAjax[liveAjax.length] = true;
$.ajax({
url: 'ajax/test.html',
success: function(data) {
liveAjax[liveAjax.length] = false;
or delete liveAjax[liveAjax.length]
}
});
then checking the alive calls by
setInterval(function(){
//looping in liveAjax and check if there any true value, then there is ajax call elese nothing happens
},200);

Categories

Resources