How do I call a JS callback when a file upload completes? - javascript

I'm creating frontend upload for an app with appengine backend.
What I want to make is a file upload solution, and I dont want to be using plupload or those kinds of ready-made solutions.
I basically submitted the images to an iframe and then put a cover while it is uploading. Then after it finishes I performed an ajax call to get the image ids for the next view to be rendered. However, the render is always called before the upload is completed, thus I'm not getting any image ids from the backend. can anyonehelp?
here's my code for the upload
perform_input3:(event)=>
event.preventDefault()
$('#product-input-3').hide()
$('#product-input-3').submit()
$('#upload-cover').show()
item_id = $('#item3_id').val()
app.views.imageselect.render(item_id)
the app.views.imageselect.render(item_id) is below:
render:(data)=>
#item_id = data
item_id = #item_id
$.ajax(
url: '/get_image_list/'
type: 'GET'
dataType: 'json'
data: {item_id: item_id}
success:(data) =>
#payload = data
$(#el).append imageSelectTemplate(#payload)
return #
)
I dont want to be using setTimeout function since it will not be flexible depending on the connection speed. Any help will be appreciated :)

Essentially, your question boils down to this: You want to wait to make your Ajax call to the server until the data you're requesting is available. Getting notifications from the server is tricky (depending on how your backend is implemented), so the best solution to your problem is probably to just make the Ajax call periodically (say, once per second) until you get a successful response from the server.
Here's some code that should do that:
do ajaxCall = =>
$.ajax
url: '/get_image_list/'
type: 'GET'
dataType: 'json'
data: {item_id: item_id}
success: (data) =>
#payload = data
$(#el).append imageSelectTemplate(#payload)
error: ->
setTimeout ajaxCall, 1000

If you are only targeting modern browsers, then XHR2's FormData can enable a very simple and elegant approach.
The concept is:
add file(s) binary data to a FormData object
make a $.ajax() call with the FormData object as the AJAX call's "data" parameter
when upload is done, the $.ajax()'s success() or complete() callbacks will be triggered
This approach works with the latest Firefox, Chrome, Safari - http://caniuse.com/xhr2.
See this post for details: Sending multipart/formdata with jQuery.ajax

What you're missing is some sort of callback from the $('#product-input-3').submit() call. I think the following would work (pardon my bad CoffeeScript):
perform_input3:(event)=>
event.preventDefault()
item_id = $('#item3_id').val()
$('#product-input-3').hide()
$('#upload-cover').show()
$('#product-input-3').submit()
$('#target-iframe').ready ->
app.views.imageselect.render(item_id)
This is predicated on the idea that calling 'submit' immediately puts the target iframe into non-ready state, which seems reasonable, but I'd test it. Once it finishes loading The other option I've seen around is to have the page the iframe loads call back into its parent (top-level) window. In JS, something like:
parent.imageUploaded()
Or, if you want to use bound events:
parent.$(parent.document).trigger('upload-complete')
Where, of course, you've set up an upload-complete event on the top-level document object.

Related

Javascript ajax request callback without waiting for response

I know we can make a javascript ajax request from some server and it either receives the response or gives timeout error after some time.
Let's consider this scenario when we don't want to wait for the request rather the server would send a response(or we can say it would be another request from server to client) async at any time after getting the request and then call a javascript CB function with the response.
I am looking for ideas for how to go about it mainly supporting all modern browsers and if possible not relying on any 3rd party plugin except may be jQuery.
The main feature of Ajax is that it IS asynchronous by default, and your program will continue to run without waiting for the response. So unless I'm misreading your question, it is what you need.
If you use jquery, then you pass in a callback function that will execute only when the server sends back a response. You can specify a timeout in the settings, though I'm not sure what the maximum time you can provide without getting a timeout error. But it will be several seconds, at least.
You can even specify different callbacks for success and fail as follows (adapted from the jquery ajax API, but added a timeout of 5 seconds):
var request = $.ajax({
url: "http://www.some.url/",
method: "GET",
data: { some : stuff },
dataType: "html",
timeout: 5000
});
request.done(function( data ) {
console.log( "SUCCESS: " + data );
});
request.fail(function() {
console.log( "Request failed");
});
I came across this question after 4 years. I dont remember in what context I asked this but for anyone who has the same query:
Http is a request/response protocol. Which means the client sends a request and the server responds to that request with some message/data. Thats the end of the story for that request.
In order for the server to trigger something on the clientside we will have to use something that keeps the connection to the server rather than ending the communication after getting the response. Socket.io is bi directional event driven library that solves this problem.
To update a cart (PHP Session storage and reserve the stock of items in database) on my online shop, I simply add a timeout of 100ms after calling it and remove Success/Error callback.
$.ajax({
url: 'http://www.some.url/',
method: 'GET',
data: {
some : 'stuff'
},
dataType: 'html',
timeout: 100
});
Note : It doesn't matter if some requests didn't arrive, because when the order is saved, an update of the whole cart is sent with a callback.
If your query needs acknowledge, don't use that solution !
I believe your question is similar to this
by Paul Tomblin. I use the answer provided by gdoron, which is also marked as the best solution, and also the comment by AS7K.
$.ajax({
url: "theURL",
data: theData
});
NB: No async parameter provided.

does using $.ajax slows down the website? what's the best way to retrieve instant data from a php file

im using alot of $.ajax calls in my website that im working on and it seems to be slow and lagging at some points. Is there any faster way to retrieve data other than using the $.ajax ?
$.ajax({
type: 'POST',
url: path + 'helper/general/general.php',
data: {pass:pass},
success: function(data){
if(data == 'correct'){
$.ajax({
type: 'POST',
url: path + 'helper/process/ClassesProcess.php',
data: {classID: classID}
});
}else{
$('.feedback').html(wrong_password).slideDown();
}
}
});
Ways in which I think you could optimise this are:
Use === instead of == in an if statement, this way it will check the type before the value.
Instead of doing an ajax call with in an ajax call, surely your first call should do all the logic (try to avoid having logic in your front-end)
Instead of returning strings or html from your ajax calls, return JSON if you can... however be wary of using json_encode/json_decode in php as they seem to be two slow functions.
If the user is refreshing the page, they don't need to redownload the content for a lot of your ajax calls, if the data hasen't changed since that user's last request, return a 304 with no data instead of returning a 200 with the data. This will make the browser get the previous response from it's cache.
Avoid declaring a function where there should be a callback, instead, put the name of a pre-existing function, this will stop the function being reinitialised every time you execute you ajax method.
Finally, when using jQuery, try to target elements by id instead of class, jQuery finds the element a lot faster this way as ids should be unique in a webpage.

Parallel JSONP requests in jQuery do not trigger multiple "callback events"?

I am experiencing an issue in jQuery when I do multiple jsonp requests, all with the same jsonpCallback function. It seems that only for the one of those the callback function is triggered. Are JSONP requests somehow overwriting each other?
Below an example of doing 2 jsonp request to github, and even though both firebug shows that both of them return, the callback function getName is only called for one of them:
function getName(response){
alert(response.data.name);
}
function userinfo(username){
$.ajax({
url: "https://api.github.com/users/" + username,
jsonpCallback: 'getName',
dataType: "jsonp"
});
}
users = ["torvalds", "twitter", "jquery"]
for(var i = 0; i < users.length; i++){
userinfo(users[i]);
}
Your request fired only once because of how jsonp works.
Jsonp means adding a script tag to the page from an outside domain to get around Cross-Site Scripting protections built into modern browsers (and now IE6 and 7 as of April 2011). In order to have that script interact with the rest of the script on the page, the script being loaded in needs to call a function on the page. That function has to exist in the global namespace, meaning there can only be one function by that name. In other words, without JQuery a single jsonp request would look like this:
<script>
function loadJson(json) {
// Read the json
}
</script>
<script src="//outsidedomain.com/something.js"></script>
Where something.js would look like this:
loadJson({name:'Joe'})
something.js in this case has a hard-coded callback to load the JSON it carries, and the page has a hard-coded loadJson function waiting for scripts like this one to load and call it.
Now suppose you want to be able to load json from multiple sources and tell when each finishes, or even load JSON from the same source multiple times, and be able to tell when each call finishes - even if one call is delayed so long it completes after a later call. This hard-coded approach isn't going to work anymore, for 2 reasons:
Every load of something.js calls the same loadJson() callback - you have no way of knowing which request goes with which reply.
Caching - once you load something.js once, the browser isn't going to ask the server for it again - it's going to just bring it back in from the cache, ruining your plan.
You can resolve both of these by telling the server to wrap the JSON differently each time, and the simple way is to pass that information in a querystring parameter like ?callback=loadJson12345. It's as though your page looked like this:
<script>
function loadJson1(json) {
// Read the json
}
function loadJson2(json) {
// Read the json
}
</script>
<script src="//outsidedomain.com/something.js?callback=loadJson1"></script>
<script src="//outsidedomain.com/somethingelse.js?callback=loadJson2"></script>
With JQuery, this is all abstracted for you to look like a normal call to $.ajax, meaning you're expecting the success function to fire. In order to ensure the right success function fires for each jsonp load, JQuery creates a long random callback function name in the global namespace like JQuery1233432432432432, passes that as the callback parameter in the querystring, then waits for the script to load. If everything works properly the script that loads calls the callback function JQuery requested, which in turn fires the success handler from the $.ajax call.
Note that "works properly" requires that the server-side reads the ?callback querystring parameter and includes that in the response, like ?callback=joe -> joe({.... If it's a static file or the server doesn't play this way, you likely need to treat the file as cacheable - see below.
Caching
If you wanted your json to cache, you can get JQuery to do something closer to my first example by setting cache: true and setting the jsonpCallback property to a string that is hardcoded into the cacheable json file. For example this static json:
loadJoe({name:'Joe'})
Could be loaded and cached in JQuery like so:
$.ajax({
url: '//outsidedomain.com/loadjoe.js',
dataType: 'jsonp',
cache: true,
jsonpCallback: 'loadJoe',
success: function(json) { ... }
});
Use the success callback instead..
function userinfo(username){
$.ajax({
url: "https://api.github.com/users/" + username,
success: getName,
dataType: "jsonp"
});
}
$(function() {
function userinfo(username){
var XHR = $.ajax({
url: "https://api.github.com/users/" + username,
dataType: "jsonp"
}).done(function(data) {
console.log(data.data.name);
});
}
users = ["torvalds", "twitter", "jquery"];
for(var i = 0; i < users.length; i++){
userinfo(users[i]);
}
}); ​
Not sure but the response I get from that call to the github API does not include gravatar_id.
This worked for me:
function getGravatar(response){
var link = response.data.avatar_url;
$('#list').append('<div><img src="' + link + '"></div>');
}

Javascript Synchronization with JSON Requests

How can I make sure that a piece of code has executed completely before executing another? I am sending some ajax requests to a server and then using the returned data to generate the rest of the webpage. the things is, is that i need to have all that data in the webpage to proceed with the rest of the code as that code will affect what has been generated and, that code, runs before the json requests and all of that have finished... is there any way I can make sure this does not happen? I managed to solve it by performing the requests and then asking the user to press a button but that is a total no-sense way of doing it.
Any ideas?
Here is some code: The problem is that the second line is executed before the first (there are many calls to similar JSON functions).
$.getJSON(url, function(data){ $("#mycontent").append("..... stuff here...... create loads of dibs with class set to mydivclass"); });
...
$("div.mydivclass").hide();
Unforunately I cannot use the ajax synchronous property because: "dataType: "jsonp" requests do not support synchronous operations"
If you are using jQuery 1.5+ you can make use of deferreds to solve your issue:
function first_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_1
);
}
function second_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_2
);
}
function final_sucess_callback() {
// Do all your display work.
}
jQuery.when(first_ajax_request(),
second_ajax_request()).then(final_success_callback);
There is an excellent article on the topic that you should read up on as well by Eric Hynds. He gives some examples of exactly the kind of problem you are trying to solve.
jquery requests are asynchonize by default , so your code does not wait for the response , so you have no guarantee that code after request will execute after the response , so you can set the request synchronize by set the async property false , now the request is synchronize and you can gurantee the rest of the code will execute after the response from the server ,
like this .
$.ajax({
url: "page.php",
processData: false,
data: xmlDocument,,
async:false,
success: handleResponse
});

Difference between $("#id").load and $.ajax?

Does anyone know what is the difference between $("#id").load and $.ajax?
Let me clarify things for you a little bit :
$.ajax() is the basic and low-level ajax function jQuery provides which means you can do what ever you want to like you can work with XmlHttpRequest object. But once upon a time jQuery Developers thought that actually besides $.ajax(), they could provide more specific methods to developers so they wouldn't need to pass more parameters to make $.ajax() method work the way they want. For example they said instead of passing json as a parameter to $.ajax() to indicate return data type, they provided $.getJSON() so we would all know that the return type we expected was json, or instead of indicating send method as post or get, you could use $.post() or $.get() respectively.
So load() is the same thing, it can help you inject html data into your html. with load() method you know that an html portion is being expected.
Isn't that cool ?
I think I've been fallen in love.
For more information, you can visit jquery.com, they are even providing their new library and api tutorial page.
Edit :
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
is the same as below :
$.post("some.php", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});
Now as you can see it is the simplified version of $.ajax(), to make post call, you need to pass some information of send method type which is post as shown at the first example but instead of doing this you can use $.post() because you know what you are doing is post so this version is more simplified and easy to work on.
But don't forget something. Except for load(), all other ajax methods return XHR (XmlHttpRequest instance) so you can treat them as if you were working with XmlHttpRequest, actually you are working with it tho :) and but load() returns jQuery which means :
$("#objectID").load("test.php", { 'choices[]': ["Jon", "Susan"] } );
in the example above, you can easly inject the return html into #objectID element. Isn't it cool ? If it wasn't returning jQuery, you should have been working with callback function where you probably get the result out of like data object and inject it manually into the html element you want. So it would be hassle but with $.load() method, it is really simplified in jQuery.
$("#feeds").load("feeds.php", {limit: 25}, function(){
alert("The last 25 entries in the feed have been loaded");
});
You can even post parameters, so according to those parameters you can do some work at server-side and send html portion back to the client and your cute jQuery code takes it and inject it into #feeds html element in the example right above.
load() initiates an Ajax request to retrieve HTML that, when returned, is set to the given selector.
All the jQuery Ajax functions are simply wrappers for $.ajax() so:
$("#id").load(...);
is probably equivalent to:
$.ajax({
url: "...",
dataType: "html",
success: function(data) {
$("#id").html(data);
}
});
A more concise summary and the most important difference is that $.ajax allows you to set content-type and datatype.
These two are important for making JSON requests, or XML requests. ASP.NET is more fussy with a missing content-type field (atleast when you use [WebMethod]) and will simply return the HTML of the page instead of JSON.
$.load() is intended to simply return straight HTML. $.ajax also gives you
caching
error handling
filtering of data
password
plus others.
From the documentation ...
$(selector).load(..)
Load HTML from a remote file and inject it into the DOM.
$.ajax(...)
Load a remote page using an HTTP request. This is jQuery's low-level AJAX implementation.
load is specifically for fetching (via GET unless parameters are provided, then POST is used) an HTML page and directly inserting it into the selected nodes (those selected by the $(selector) portion of $(selector).load(...).
$.ajax(...) is a more general method that allows you to make GET and POST requests, and does nothing specific with the response.
I encourage you to read the documentation.
Here's the source code for the load function: http://github.com/jquery/jquery/blob/master/src/ajax.js#L15
As you can see, it's a $ajax with some options handling. In other words, a convenience method.
The above answer may not be valid anymore in light of the use of deferred and promise objects. I believe that with .ajax you can use .when but you cannot do so with .load. In short, I believe that .ajax is more powerful than .load. For example:
some_promise = $.ajax({....});
.when(some_promise).done(function(){.... });
You get more granular control over the html loading. There is also .fail and .always for failure and "no matter what" cases. You don't get this in load. Hope I am correct on this.

Categories