I wrote a simple snippet to load dynamically pages parts as follows:
function LoadParts(container) {
$("a._Part", container).each(function () {
element = $(this);
url = $(this).attr("href");
$.get(url, null, function (text, status) {
var c = $(element).parent("span");
c.html(text);
LoadParts(c);
});
});
}
I was tracing the traffic with Fiddler while I was browsing it using IE 8.0, and I saw a magic happens here, for some calls it used a cached value, and for some others got a fresh one.
You should be using the ajax method
http://api.jquery.com/jQuery.ajax/
$.ajax(url,
{
cache: false,
success: function(){
//do something
}
}
);
Related
I've been using the following code for doing ajax calls in Angular which worked fine so far:
function getData (url) {
var deferred = $q.defer();
$http.get(url, {
cache: true
}).success(function (data) {
deferred.resolve(data); // works
});
return deferred.promise;
}
As you can see there is only a success handler. When I wanted to add an error handler, I noticed that the docs state that success and error were depracated and should not be used any more (https://docs.angularjs.org/api/ng/service/$http). Instead the .then promise should be used, so I changed my code to this:
function getData (url) {
var deferred = $q.defer();
$http.get(url, {
cache: true
}).then(function (data) {
deferred.resolve(data); // Not called :(
}, function () {
deferred.resolve(false); // Not called :(
});
return deferred.promise;
}
Now everything stopped working. .then is never called. Why? I'm on latest Angular version 1.4
Ok, I found the problem. Actually, there were two problems.
First, I had a redundant promise which I removed:
function getData (url) {
return $http.get(url, {cache: true});
}
Second, the returned data from .then seems to be a little different from .success. Instead of returning the plain result data, it returns an object with some meta data from the call. So, in order to get the data, I'd have to access data.data:
pub.getList = function () {
return getData(serviceurl + "?c=latest").then(function (result) {
var list = result.data;
precacheArticles(list);
return list;
});
};
The problem is very simple: i have to download a file when i submit a form, it's an ajax call when the form is submitted which lets me build a file with the data taken from the form, server side, and then send it as a link to an alert. The fact is that my boss want the file to be downloaded directly and not through a link in an alert. So i had to make sure that the file is available server side through tornado(web):
self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=clients_counter.zip')
with open("static/clients_counter.zip", 'r') as f:
while True:
data = f.read()
if not data:
break
self.write(data)
self.finish()
The server side code seems to work fine, but the client side (extjs4.1) is really a nightmare. This is how my ajax call looks like now, and it doesn't work:
Ext.Ajax.request({
method : "GET",
url : 'http://whatever.com/count?client='+client+'&start='+start+'&end='+end,
timeout : 30000,
success :
function (response) {
//Ext.Msg.alert(response.responseText);
desktop.getWindow('count-win').doClose();
return response;
}//handler,
failure :
function(response) {
alert("Wrong request");
}});
After reading on various sources from Ext JS forum and here in stackoverflow, below is the approach I've chosen (using Ext JS version 4.2.1):
downloadFile: function(config){
config = config || {};
var url = config.url,
method = config.method || 'POST',// Either GET or POST. Default is POST.
params = config.params || {};
// Create form panel. It contains a basic form that we need for the file download.
var form = Ext.create('Ext.form.Panel', {
standardSubmit: true,
url: url,
method: method
});
// Call the submit to begin the file download.
form.submit({
target: '_blank', // Avoids leaving the page.
params: params
});
// Clean-up the form after 100 milliseconds.
// Once the submit is called, the browser does not care anymore with the form object.
Ext.defer(function(){
form.close();
}, 100);
}
I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:
Make a standard sumbit instead of Ajax.
var form = Ext.create('Ext.form.Panel', { // this wolud be your form
standardSubmit: true, // this is the important part
url: '../ObtenerArchivoAdjuntoServlet'
});
form.submit({
params: {
nombreArchivo: nombreArchivo
}
});
After this you would be able return the desired file.
After extracting/reading many posts, I managed to get this simple method to work..
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
standardSubmit: true,
url: 'URL'
}).submit({params: {'PARAM1': param1, 'PARAM2': param2}});
I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:
window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)
This will open a new tab and start the download from there.
The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.
use an iframe like this:
/**
* prints the file
*/
printReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
Ext.DomHelper.append(Ext.getBody(), {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: url
});
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
Copied the answer from extjs forum
Option:2
If you want to open the file in new tab
/**
* open file in tab
*/
openReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
var win = window.open('', '_blank');
win.location = url;
win.focus();
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.
FileDownload.downloadFile = function(arguments) {
var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];
var body = Ext.getBody();
var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});
var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});
if (params) {
for (var paramName in params) {
form.createChild({
tag:'input',
cls:'x-hidden',
id:'hiddenform-'+paramName,
type: 'text',
text: params[paramName],
target:'iframe',
value: params[paramName],
name: paramName
});
}
}
form.dom.submit();
FileDownload.isFinished(successCallback,failureCallback);
};
FileDownload.isFinished = function(successCallback,failureCallback) {
//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
//Remove cookie call success callback
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
successCallback();
return;
}
//Check for error / IF any error happens then frame will load with content
try {
if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
failureCallback();
//Cleanup
Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = "";
return;
}
}
catch (e) {
console.log(e);
}
console.log('polling..');
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);
};
Usage :
FileDownload.downloadFile({
url : url,
params : params,
success : function(){
//Success call back here
},
failure : function(){
//Failure callbak here
}
});
In the http response you need to add a cookie nammed fileDownload = true
I just had to ad to the success function of the ajax request:
window.open('urltothefile.ext')
I have an old code which is dependant on JQuery 1.3.2 that uses the following ajax call
function ChangeContent(url, somepageobject) {
var xhrobj = $.ajax({
url: url,
context: somepageobject,
callback: doFurtherStuff,
success: function(data) {
somepageobject.html($(data));
this.callback.call(this.context[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
Problem with the code above is that this.callback is null when I upgraded to JQuery 1.8.1, most importantly the ChangeContent function is being used in different places and is outside my control (its used as as an API for external users...etc). An example of the usage of the above is like this:
xhr_object = ChangeContent("/someurl, $("#resultContainer"));
function doFurtherStuff(responseText, statusText, XMLHttpRequest)
{
var identifier = '#' + this.id;
...
}
Notice that the doFurtherStuff must have the correct "this" object value which is the context specified in ChangeContent function. When I tried to use different deferred then() ...etc. functions in JQuery 1.8.1 to solve the above this.callback.call(this.context[0], data); problem after the upgrade the "this" object in the callback function had different value since I guess the new JQuery library handles that differently.
Is there anyway to fix the error above while limiting the change to ChangeContent function only as I try to avoid asking all users to change the way they call and handle call backs from that function?
When you add the context option, you are telling jQuery what this should be inside of the success callbacks. That means you can't access the options passed into the ajax request. Either don't supply a context, or pass in the callback manually.
function ChangeContent(url, somepageobject) {
var callback = doFurtherStuff;
var xhrobj = $.ajax({
url: url,
context: somepageobject,
success: function(data) {
somepageobject.html($(data));
callback.call(this[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
Update:
If you want to instead continue using your code as-is, simply rename the context property.
function ChangeContent(url, somepageobject) {
var xhrobj = $.ajax({
url: url,
thecontext: somepageobject,
callback: doFurtherStuff,
success: function(data) {
somepageobject.html($(data));
this.callback.call(this.thecontext[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
I'm using a formatter on one of my columns in jqGrid. The formatter uses some logic to decide what to display, and in some cases, it calls an ajax method. I've verified in Fiddler that the proper data comes back from my ajax calls. I've also verified in Chrome degbugging tools, that my variables are getting set properly. However, the sequence is all out of sorts, so the returned value in my column is "undefined". I can see in debugging tools' timeline that my getJSON calls are getting called after the jqgrid is already loaded.
I tried this first:
function myFormatter(cellvalue, options, rowObject)
{
if (rowObject[0] == something) {
$.getJSON('#Url.Action("MyAction", "MyController"), function (myResult) {
var myObject = myResult[0];
return myObject.myID;
});
}
else {
return "";
}
}
I also tried using an ajax call w/ async=false and I've tried different values for type and dataType, but the results are all the same:
function myFormatter(cellvalue, options, rowObject)
{
if (rowObject[0] == something) {
$.ajax({
type: 'POST',
url: '#Url.Action("MyAction", "MyController"),
async: false,
success: (function(result) {
var myObject = myResult[0];
return myObject.myID;
})
});
}
else {
return "";
}
}
It seems like you should be able to get this to work by using a synchronous AJAX call and a closure:
function myFormatter(cellvalue, options, rowObject)
{
var value = "";
if (rowObject[0] == something) {
$.ajax({
type: 'POST',
url: '#Url.Action("MyAction", "MyController"),
async: false,
success: (function(result) {
var myObject = myResult[0];
value = myObject.myID;
})
});
}
return value;
}
In general it is bad practice to use synchronous AJAX calls though, because they can block the UI for an undetermined amount of time. This case could be especially bad if you have a lot of rows in your grid, because one AJAX call will be made per row.
If you can, a better approach might be to either retrieve the ID's ahead of time and cache them locally on the page, or just do the formatting server-side. As always, use your best judgement.
Hey. I need some help with jQuery Ajax calls. In javascript I have to generste ajax calls to the controller, which retrieves a value from the model. I am then checking the value that is returned and making further ajax calls if necessary, say if the value reaches a particular threshold I can stop the ajax calls.
This requires ajax calls that need to be processes one after the other. I tried using async:false, but it freezes up the browser and any jQuery changes i make at the frontend are not reflected. Is there any way around this??
Thanks in advance.
You should make the next ajax call after the first one has finished like this for example:
function getResult(value) {
$.ajax({
url: 'server/url',
data: { value: value },
success: function(data) {
getResult(data.newValue);
}
});
}
I used array of steps and callback function to continue executing where async started. Works perfect for me.
var tasks = [];
for(i=0;i<20;i++){
tasks.push(i); //can be replaced with list of steps, url and so on
}
var current = 0;
function doAjax(callback) {
//check to make sure there are more requests to make
if (current < tasks.length -1 ) {
var uploadURL ="http://localhost/someSequentialToDo";
//and
var myData = tasks[current];
current++;
//make the AJAX request with the given data
$.ajax({
type: 'GET',
url : uploadURL,
data: {index: current},
dataType : 'json',
success : function (serverResponse) {
doAjax(callback);
}
});
}
else
{
callback();
console.log("this is end");
}
}
function sth(){
var datum = Date();
doAjax( function(){
console.log(datum); //displays time when ajax started
console.log(Date()); //when ajax finished
});
}
console.log("start");
sth();
In the success callback function, just make another $.ajax request if necessary. (Setting async: false causes the browser to run the request as the same thread as everything else; that's why it freezes up.)
Use a callback function, there are two: success and error.
From the jQuery ajax page:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
// Do processing, call function for next ajax
}
});
A (very) simplified example:
function doAjax() {
// get url and parameters
var myurl = /* somethingsomething */;
$.ajax({
url: myurl,
context: document.body,
success: function(data){
if(data < threshold) {
doAjax();
}
}
});
}
Try using $.when() (available since 1.5) you can have a single callback that triggers once all calls are made, its cleaner and much more elegant. It ends up looking something like this:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
// a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
alert( jqXHR.responseText )
});