detect a 407 error and persist for all subsequent requests - ajax

I have a simple javascript that uses $.ajax() from JQuery which works great for GET/POST. However, for some users that are behind a proxy, they receive the 407 error as outlined in the post below.
407 Proxy Authentication Required
Now, as you will see, I've updated that post stating that the usage of JSONP will suffice as a workaround. Where I'm at now, is I don't want to use JSONP all the time, only when it is required.
function original() {
$.ajax({
url: "http://somecool.url/foo",
data: { id:"bar"},
statusCode: {
407: foo()
},
success: function(data) {
$.each(data, function(k,v) {
$('#foo').append("<li>" + k + ":" + v + "</li>");
});
}
});
}
function foo() {
$.ajax({
url: "http://somecool.url/foo",
data: { id:"bar" },
dataType: "jsonp",
success: function(data) {
$.each(data, function(k,v) {
$('#foo').append("<li>" + k + ":" + v + "</li>");
});
}
});
}
$(document).ready(function() {
original();
});
Is it possible to persist the status of the first failure, which returns the 407 error when there is a proxy issue so that all subsequent requests do not go to the original() function and go to the foo() function?

My original answer (below) was dealing with function name override to accommodate the code in your question. However, there's a better solution, since after all you only want to switch all requests to JSONP if and only if you receive a 407 response code.
$.ajaxSetup() was designed to do exactly that:
function original() {
$.ajax({
url: "http://somecool.url/foo",
data: { id:"bar"},
statusCode: {
407: function() {
$.ajaxSetup({ dataType: "jsonp" });
// Now all AJAX requests use JSONP, retry.
original();
}
},
success: function(data) {
$.each(data, function(k,v) {
$('#foo').append("<li>" + k + ":" + v + "</li>");
});
}
});
}
With this strategy, once 407 is received, all the future AJAX requests will use JSONP.
For the sake of history, here is my original answer.
You can permanently change the function stored in original when you receive a 407 response code for the first time:
function original() {
$.ajax({
url: "http://somecool.url/foo",
data: { id:"bar"},
statusCode: {
407: function() {
window.original = foo;
foo();
}
},
success: function(data) {
$.each(data, function(k,v) {
$('#foo').append("<li>" + k + ":" + v + "</li>");
});
}
});
}
From then on, the name original will refer to foo(). You can even change the function and call its replacement at the same time:
407: function() {
(window.original = foo)();
}

Related

Display all data fetched, api rest using __next

I need to fetch all data from an xml link but I couldn't as it displays only 300 rows, so I found a solution that says I should use __next, I have the code below but it doesn't work, in the console I get the next url but the items (TaskName) of the first page. I want to get the TaskName(s) of the next pages.
window.addEventListener('load',function() {
$.ajax({url: _spPageContextInfo.siteAbsoluteUrl + "/_api/ProjectData/[en-US]/Tasks",
method: "GET",
dataType: "json",
headers: {Accept: "application/json;odata=verbose"},
success: function(data) {
var dataResults = data.d.results;
if (data.d.__next) {
url = data.d.__next;
console.log("url: "+url);
}
$.each(dataResults, function(key, value)
{
var tasky = value.TaskName;
console.log(tasky);
});
}});
});
I found a solution, here the code is:
function GetListItems(){
$.ajax({
url: urly,
method: "GET",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data){
response = response.concat(data.d.results);
if (data.d.__next) {
urly = data.d.__next;
GetListItems();
}
$.each(response, function(key, value)
{
var tasky = value.TaskName;
console.log(tasky);
});
},
error: function(error){
}
});
}

Combine AJAX and API calls

I am working with APIs. My logic is 1st add a grade (POST), 2nd get the gradeID (GET), 3rd add grades to students (PUT). My problem is that I have to use the gradeID in the API call to add the grades.
How do I do using AJAX to get the result from one call and then pass to another call?
here is my ajax:
$.ajax({
type: 'post',
url: "doRequest.php",
data: postData,
success: function(data) {
var output = {};
if(data == '') {
output.response = 'Success!';
} else {
try {
output = jQuery.parseJSON(data);
} catch(e) {
output = "Unexpected non-JSON response from the server: " + data;
}
}
$('#statusField').val(output.statusCode);
$('#responseField').val(format(output.response));
$("#responseField").removeClass('hidden');
$("#responseFieldLabel").removeClass('hidden');
},
error: function(jqXHR, textStatus, errorThrown) {
$('#errorField1').removeClass('hidden');
$("#errorField2").innerHTML = jqXHR.responseText;
}
});
}
Is there a way tho have an ajax inside of other?

What's the correct way to iterate through array and sending multiple ajax requests

I currently have some ajax that sends an array to php for processing. The array size at most would be around 1000 elements which will be enough for the server to time out while the php is processing. I would like to chunk the array and send it in batched ajax requests (or maybe just one at a time) that will each finish without timing out.
Below is my basic code structure. I'm trying to use promises and iterate through the chunks:
Here's the basic structure of the working function (non-promise version):
function ajax_function(big_array) {
$.ajax({
type: 'POST',
url: ajax.ajax_url,
data: {
'action': 'process_big_array',
'array_to_process': big_array
},
beforeSend: function () {
xxx
},
dataType: 'json',
success: process_big_array_chunk_handler,
error: function (xhr, desc, err) {
console.log(xhr);
console.log('Details: ' + desc + '\nError: ' + err);
}
});
}
Here's work in progress trying to add the loop and promise.
function ajax_function(big_array) {
var big_array_chunks = make it into chunks somehow;
$.each(big_array_chunks, function (big_array_chunk) {
var request = $.ajax({
type: 'POST',
url: ajax.ajax_url,
data: {
'action': 'process_big_array_chunk',
'array_to_process': big_array_chunk
},
dataType: 'json'
}).done(function (data) {
process_big_array_chunk_handler(data);
}).fail(function (xhr, desc, err) {
console.log(xhr);
console.log('Details: ' + desc + '\nError: ' + err);
});
});
}
Trying to get my head around how this all fits together:
each iteration of loop
responses from php
how to use my response handler when it's all done
fyi, this is being done within the context of WordPress if that matters.
Response to Bergi:
function ajax_function(big_array) {
var big_array_chunks = make big_array into chunks somehow;
var request = $.ajax({
type: 'POST',
url: ajax.ajax_url,
data: {
'action': 'process_big_array_chunk',
'array_to_process': big_array_chunk
},
dataType: 'json'
}).then(function (data) {
process_big_array_chunk_handler(data);
});
}
The simplest solution I can think of is to just pre-chunk the array and then just use the .reduce() design pattern for serializing promises.
function processBigArray(bigArray, chunkSize) {
// pre-split array into chunks
var chunkArray = [];
for (var i = 0; i < bigArray.length; i+=chunkSize) {
chunkArray.push(bigArray.slice(bigArray, i, chunkSize));
}
var results = [];
// use .reduce() design pattern for chaining and serializing
// a sequence of async operations
return chunkArray.reduce(function(p, chunk) {
return p.then(function() {
return $.ajax({
type: 'POST',
url: ajax.ajax_url,
data: {
'action': 'process_big_array',
'array_to_process': chunk
},
beforeSend: function () {
xxx
},
dataType: 'json',
}).then(function(data) {
results.push(data);
});
});
}, Promise.resolve()).then(function() {
// depending upon what your ajax returns, results might be an array of arrays
// that you would want to flatten
console.log(results);
return results;
});
}
// usage
processBigArray(someBigArray, 50).then(function(results) {
// process results here
}).catch(function(err) {
// deal with error here
console.log(err);
});

How do you call a common controller method from ajax?

I am using the Nancy framework in asp.net-mvc. From within the various views, I'd like to be able to call methods from a common module via ajax/getJSON rather than having to duplicate end points in each controller module but have been unsuccessful so far.
Suppose my controller module looks like this:
namespace SomeNamespace
{
using Microsoft.EntityFrameworkCore;
using Models;
using Nancy;
public class CommonModule : NancyModule
{
public CommonModule(IAppRepository repo)
{
Get("/EndpointName/{someargument}", async (x, ct) =>
{
string result = string.Empty;
int someargument;
if(int.TryParse(x.apptype, out someargument))
{
var data = await repo.SomeModel.AsNoTracking().ToListAsync().ConfigureAwait(false);
result = Response.AsJson(data);
}
return result;
});
}
}
}
Within my js file, I'd have something like:
function callMethod()
{
var someargument = $('#SomeControl').data('somedata');
var url = window.location.protocol + '/' + window.location.host + '/CommonModule/EndpointName/' + someargument;
$.getJSON(url, function (json) {
//process if/as required;
})
.done(function (info) {
//process if/as required;
})
.fail(function (jqxhr, textStatus, error) {
//process if/as required;
});
}
Is this possible? If so, how is this done? Am I just constructing the url incorrectly or is it to do with ensuring the correct reference is present in the .cshtml file?
Try something like:
$('#CommonModulebtn').click(function () {
$.ajax({
url: '/CommonModule/CommonModule',
type: "GET",
dataType: "JSON",
data: { IAppRepository : $('#SomeControl').data('somedata').val() },
success: function (info) {}
function callMethod() {
$.ajax({
url: "/CommonModule/CommonModule",
type: "GET",
data: $("#IDFORM").serialize(),
dataType: "json",
success: function (data, textStatus, jqXHR) {
alert("ok");
},
error: function (data) {
alert("error");
}
})
}
You can call any controller action from any controller view within your application. And your code is fine. You need to make sure that you construct correct URL.
I am not familiar with NancyFx routing, but I think that You need to remove 'CommonModule' from the URL so it looks like:
var url = window.location.protocol + '/' + window.location.host + '/EndpointName/' + someargument;
If it is a common module, you may want to change the route on the server:
public CommonModule(IAppRepository repo)
{
Get("/common/EndpointName/{someargument}", async (x, ct) => ...
and the URL in JavaScript will be
var url = window.location.protocol + '/' + window.location.host + '/common/EndpointName/' + someargument;

BreezeJs - How to make simultaneous AJAX calls?

I wrote two Ajax calls that request data from stored procedures (in SQL Server), sp_ahtreatmentselect and sp_inventoryselect. Here is how the functions look like in the Breeze controller.
[HttpPost]
[ActionName("getinventories")]
public object GetInventories(HttpRequestMessage request)
{
var data = request.Content.ReadAsFormDataAsync().Result;
var opId = data["operationid"];
string query = "sp_inventoryselect #operationId";
SqlParameter operationId = new SqlParameter("#operationId", opId);
return UnitOfWork.Context().ExecuteStoreQuery<GetInventories>(query, operationId);
}
[HttpPost]
[ActionName("gettreatments")]
public object GetTreatments(HttpRequestMessage request)
{
var data = request.Content.ReadAsFormDataAsync().Result;
var opId = data["operationid"];
string query = "sp_ahtreatmentselect #operationId";
SqlParameter operationId = new SqlParameter("#operationId", opId);
return UnitOfWork.Context().ExecuteStoreQuery<GetTreatments>(query, operationId);
}
Now, on client-side, the Ajax calls look like this:
var ajaxImpl = breeze.config.getAdapterInstance('ajax');
function treatments(id) {
return ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/gettreatments',
data: { operationid: id },
success: function(data) {
console.log('Success!');
},
error: function(error) {
console.log('Error!');
}
});
}
function inventories(id) {
return ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/getinventories',
data: { operationid: id },
success: function (data) {
console.log('Success!');
},
error: function(error) {
console.log('Error!');
}
});
}
return inventories(id).then(treatments(id))
.then(function() {
// Do something
})
.fail(function(error) {
// Display error
});
Both Ajax calls work fine, BUT problem is, // Do something is run BEFORE inventories(id) and treatments(id) are run. I would like it to work the other way around instead. I also tried $.when(inventories(id), treatments(id)).then(...) and $.when(ajaxImpl.ajax(...), ajaxImpl.ajax(...)).then(...), but same problem occurs. How do I solve this?
Thanks in advance.
I realized that the issue lay on synchronous calls, not Breeze. I used queue.js to make Ajax calls and // Do something and the calls are completed. Here is how.
var ajaxImpl = breeze.config.getAdapterInstance('ajax'),
serviceName = 'some/service',
id = 1; // Could be any number
return queue()
.defer(function(callback) {
ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/getinventories',
data: { operationid: id },
success: function (data) {
console.log('Success!');
callback(null, data);
});
})
.defer(function(callback) {
ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/gettreatments',
data: { operationid: id },
success: function (data) {
console.log('Success!');
callback(null, data);
});
})
.awaitAll(function(error, results) {
if (error) {
console.log('Error! ' + error);
} else {
// Do something, given that:
// results[0] are inventories, and
// results[1] are treatments
}
});
I don't know what this has to do with Breeze. Did you get your ajaxImpl from a Breeze ajax adapter? I've looked at both ajax adapters shipped with Breeze and neither of them returns anything from a call to the ajax method!
Accordingly, you're expression should have died immediately with a reference error when it got to the .then in return inventories(id).then(.... I don't see how it could have gotten to \\ do something at all.
Something isn't right with the way you've posed this question.
Once you get beyond this I still don't see how this involves Breeze. Breeze won't do anything with the results of your service requests.
I'm completely flummoxed by your question.

Resources