Using .ajaxComplete() with ajax requests generated by another framework - javascript

I need to execute a few scripts on a page whose ajax requests (onchange/onclick on different elements) are constructed using a custom framework that I cannot change. Fundamentally, I would like to, on successful completion of specific request, execute a few scripts that I have written. Is it possible to use ajaxComplete() or ajaxSuccess() when the ajax call was not initiated using jQuery?

No. Those are part of the event handling jQuery adds to the events it fires off itself.
I don't think there's an event fired when any ajax request at all finishes; your best option is to wrap the XHR constructor before loading this other framework and restore it afterwards. Even that may not work depending on what the framework is actually doing.
Can you be more specific about what this other code is and what you want to add to it? There are events that fire when the page is mutated, for instance, which might be more appropriate.

Related

Rails implementation of input tag firing event on value change

I was wondering if there is some cleaner way to implement event firing on input tag value change (i want it to fire every time character is entered/deleted) and make these values visible in controller other than using ajax?
So the way I know now is implementing JavaScript snippet which would attach addEventListener to input element (like here) and would make ajax call to initial rails controller to pass the new input tag value. However ajax feels like too much as opposed to if there would be something native in rails, I just can't seem to find it.
If you need anything from browser going out to server (written in any language) without refreshing the page, Ajax is the way to go. Now-a-days, fetch would be another alternative, which works in similar manner.
If you need every key-stroke to be sent to server (controller), you should add a keyup event listener. In the event listener function, make an Ajax/fetch call to the endpoint, and return relevant information from your controller.
Do remember to include a timestamp in the requests, and send them back in response though. In most such scenarios, you'd want to be differentiate between "what is new" vs "what is stale", in case user types too fast. Due to network delays, responses typically do not come back in same order as the requests were made in.

If Call js file as async function undefined in javascript [duplicate]

If you use plain script tags on an HTML page, rendering is blocked until the script has been downloaded and parsed. To avoid that, for faster page display, you can add the 'async' attribute, which tells the browser to continue processing down the page without waiting for that script. However, that inherently means that other javascript that refers to anything in that script will probably crash, because the objects it requires don't exist yet.
As far as I know, there's no allScriptsLoaded event you can tie into, so I'm looking for ways to simulate one.
I'm aware of the following strategies to defer running other code until an async script is available:
For a single script, use their 'onload' event or attribute. However, there's no built-in way I know of to tell when ALL scripts have loaded if there's more than one.
Run all dependent code in onload event handlers attached to the window. However, those wait for all images too, not just all scripts, so the run later than would be ideal.
Use a loader library to load all scripts; those typically provide for a callback to run when everything has loaded. Downside (besides needing a library to do this, which has to load early), is that all code has to wrapped in a (typically anonymous) function that you pass into the loader library. That's as opposed to just creating a function that runs when my mythical allScriptsLoaded fires.
Am I missing something, or is that the state of the art?
The best you could hope for would be to know if there are any outstanding async calls (XMLHttpRequest, setTimeout, setInterval, SetImmediate, process.nextTick, Promise), and wait for there to not be one. However, that is an implementation detail that is lost to the underlying native code--javascript only has its own event loop, and async calls are passed off to the native code, if I understand it correctly. On top of that, you don't have access to the event loop. You can only insert, you can't read or control flow (unless you're in io.js and feeling frisky).
The way to simulate one would be to track your script calls yourself, and call after all script are complete. (i.e., track every time you insert a relevant script into the event loop.)
But yeah, the DOM doesn't provide a NoAsyncPending global or something, which is what you'd really require.

Why are busy indicators not displayed when sending requests?

I have some slow OData calls which need to present some sort of visual indicator to the user that something is happening.
I've read the API reference and seen functions like attachRequestSent(), setBusy(), BusyDialog, BusyIndicator, etc.
I tried using them accordingly but did not work for me. The problem seems to be oModel.create causing the whole app to hang while it executes. No loading indicators or anything can run since the app is frozen until the create function has returned.
Edit: I have set up an asynchronous batch read OData call. I have then wrapped the code for handling the received data in a function and called that function inside the success function in the batch call.
This works; the view loads and I see a busy indicator before the fields are populated with the data
oModel.submitBatch(/*fnSuccess*/);
Is this a good way to do it, or is there a better way which is more standard?
Before the Odata call, display the busy indicator (locks the entire app screen). with
sap.ui.core.BusyIndicator.show(0);
Then, in both the success and failure handlers of the odata call, hide it with
sap.ui.core.BusyIndicator.hide();
It does not work with implicit calls (when for instance you bind to an odata model), for this you can use the request sent events, but the idea is the same.
Edit: You also need to give a small delay to allow the indicator to appear, then use setTimeout to call your odata after a small delay.
doStuffWithIndicator: function(){
sap.ui.core.BusyIndicator.show(0);
setTimeout(function(){
doStuff();
sap.ui.core.BusyIndicator.hide();
}, 20);
},
checkout this thread: SAPUI5 Wait for an Deferred-Object // wait for .done() function
Javascript is asynchrone, this means the code will be processed further no matter if you make an call (which might take longer). Therefore before calling an OData Service you need to tell your JS to wait for it (make it synchrone) via an deferred object.
The main problem seems to be oModel.create causing the whole app to hang while it executes. No loading indicators or anything can run since the app is frozen until the create function has returned.
Sounds like you've been using the now-deprecated sap.ui.model.odata.ODataModel the whole time, which sends mostly synchronous XHRs. Synchronous XHRs block the main thread (== UI thread) until the browser receives the response. The browser isn't then able to update the DOM to display the busy indicator during the round trip.
If anyone reading this has the same issue, please migrate to the newer equivalent model: sap/ui/model/odata/v2/ODataModel. It sends only asynchronous requests (AJAX), allowing the UI thread to handle other tasks (such as adding the busy indicator to the DOM) while the browser waits for the response.

How can I track AJAX calls and determine whether calling the callback function is no longer necessary?

I have a web application that is growing more complex. It makes heavy use of JavaScript based HTML generation and AJAX calls, and herein lies my problem:
Since I can't know how long an ajax call might take getting back to client side, I don't know when the callback gets actually executed. The user might have at that point navigated away from the element that originally caused the AJAX event, in which case this callback can cause some havoc. Is there a way to "expire" old callbacks ?
Are there any libraries that would offer that functionality? (I am using jQuery now but am not 100% familiar with it).
Thanks,
You might want to look into Ajax Queue Manager. There are params you can set to abort old requests before sending a new one. I think that might be what your looking for.
Well, the simple answer is to check for the proper state of your app within your callback functions, before they do whatever it is they are doing that causes problems. For example, you could make sure that certain elements are still being hovered over.

How can I find out which Javascript causes an Ajax request?

I'm having a problem with a Java JSF application: In a certain case, a user action causes an Ajax HTTP request that updates the UI correctly, but then immediately a second request is triggered, causing a second, incorrect update.
How can I find out (preferably using Firebug) where exactly that second request is triggered? There's a lot of minified framework JS code, so I don't know where to place breakpoints. Setting the form onsubmit handler to console.trace did not help, I suppose because these are independant Ajax requests.
While trying out the suggestions in the answers, I found that Firebug already has exactly what I need out of the box: the Console tab displays all requests, and for Ajax requests it shows the file and line number where they originate, which tells me where to set my breakpoint...
Using Firebug you can set Breakpoints on DOM (HTML) Mutation Events if you have some HTML changes in your UI update.
If the framework abstracts the AJAX requests, you should be able to trace the calls to the abstractions. For example, jQuery allows this through its global AJAX event handlers.
Another, more robust way to tackle the problem would be to replace the XHR object and trace calls made to it (i.e. if the framework does not provide the above abstraction or if the calls that you want to use don't use the abstraction). Just replace the GM_log with console.trace in the script at the end of the page and include it in the page you're testing.
What I personally have done in these case is using an HTTP proxy that can put a request or response 'on hold'. E.g. Burp Proxy (this is actually a security tool, but it works great for debugging purposes)
Start up the proxy and configure your browser to use it. Navigate to the page where the roque requests originates from and activate intercepting requests (this might take some practice as Burp Proxy can be a rather complicated tool).
Now do the user action, if all goes well the proxy intercepts it and waits for your confirmation to let it go through. Do this. Then you'll probably see the second request coming and being intercepted by the proxy as well. Don't let this one through, but instead switch to Firebug and suspend into the debugger. Hopefully you'll then be able to see where it originates from. Edit: on second thoughts, the asynchronous nature of AJAX probably means you won't be able to see what the exact spot is via this method anyway... :(
At least you can also configure it to intercept responses. Both requests and responses can be edited on the fly, which can be great for experimenting and debugging and might help in narrowing down the problem.
Might this would help, caller is a method in Function object of javascript.
console.log(arguments.callee.caller.toString());

Categories