I have a very unique setup, which I imagine is having some effect on this issue (which I've never seen before).
I'm writing a Google Chrome Extension, and I'm relying on Node.js as my backend.
When I run multiple Ajax requests, and Node.js takes a long time to respond (for instance, 2.5 seconds) some of the Ajax requests will never receive the response and throw an error.
I've set up a test function in my Node.js server that will respond with a JSON object after waiting for 2500 ms. I've confirmed this works with a single request.
Then, I've tried embedding jQuery in the Extension and trying two requests:
(function(){
$.ajax({
url : url,
data : params,
type : "POST",
success : function(data){
alert('success1');
},
error : function(xmlhttprequest, textstatus, message) {
alert('error');
}
});
})();
(function(){
$.ajax({
url : url,
data : params,
type : "POST",
success : function(data){
alert('success2');
},
error : function(xmlhttprequest, textstatus, message) {
alert('error');
}
});
})();
In this case, only the second alert is called. The first one will eventually result in an error (timeout).
I also tried without jQuery, like so:
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
alert('response1');
}
xhr.send();
var xhr2 = new XMLHttpRequest();
xhr2.open("POST", url, true);
xhr2.onreadystatechange = function() {
alert('response2');
}
xhr2.send();
In this case, both of the requests fail; I don't receive a response from either one.
I've also tried this code in a background script, running on an auto generated background page. This also fails (neither success works).
I'm guessing this is related in some way to the very niche case I'm writing here, but at this point I'm really at a standpoint as to how to troubleshoot and move forward. Any ideas for exploring this issue further?
Thanks!
Kevin
Related
What sort of situations could cause this handler to be called? I'm not finding any instance where this method throws an error.
I tried with the device offline, I get xmlHttpRequest.status = 0 but no error.
Question is what sort of situations can I create in order to test functionality of this handler.
var xmlhttp = new XMLHttpRequest(),
method = 'GET',
url = 'https://developer.mozilla.org/';
xmlhttp.open(method, url, true);
xmlhttp.onerror = function () {
console.log("** An error occurred during the transaction");
};
xmlhttp.send();
From: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror
Your question is the perfect example. Just try your code from your web developer console while on this very page.
Here, try it yourself:
var xmlhttp = new XMLHttpRequest(),
method = 'GET',
url = 'https://developer.mozilla.org/';
xmlhttp.open(method, url, true);
xmlhttp.onerror = function () {
console.log("** An error occurred during the transaction");
};
xmlhttp.send();
When dealing with any network based IO all kinds of things could happen. Cross-Origin requests are only one. What if the server is offline, DNS lookup fails, a router between you and the server that is critical point of failure goes down?
Since an XHR call is for a server response, onerror would come into play when there is an error at the server. Changing your client to be offline doesn't simulate a server error.
Suppose the server resource gets moved and the server responds with a 404 error? What if the server times out? What if the request itself is malformed and causes the server to throw an error?
Heres my email sending function:
function send() {
var key = "dJdJekCVAFIqvUJ13DEczZjgIh_4MyeIGEHz2GBYKFe";
var message_name = "defender_send_message";
var data = {};
data.value1 = document.getElementById('textBox').value;
data.value2 = localStorage.getItem("AdminsEmail");
var url = "https://maker.ifttt.com/trigger/" + message_name + "/with/key/" + key;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
console.log("Message Sent");
}
}
}
xmlhttp.open('POST', url, true);
xmlhttp.responseType = 'json';
xmlhttp.send(new FormData(data));
}
I wanted to create an email sending function with only pure js, not jquery or anything. I get the following errors when i click send:
(ignore the first error i fixed that already)
I had a jquery function that worked (but i had to get rid of it):
var message = localStorage.getItem("Message");
console.log(message + localStorage.getItem("AdminsEmail"));
var key = "dJdJekCVAFIqvUJ13DEczZjgIh_4MyeIGEHz2GBYKFe"; // << YOUR KEY HERE
var message_name = "defender_send_message"; // << YOUR MESSAGE NAME HERE
var url = "https://maker.ifttt.com/trigger/" + message_name + "/with/key/" + key;
$.ajax({
url: url,
data: {value1: message,
value2: localStorage.getItem("AdminsEmail")},
dataType: "jsonp",
complete: function(jqXHR, textStatus) {
console.log("Message Sent");
}
});
why would this work and my other function not?
EDIT 2 : Since it seems the endpoint doesn't actually return JSON, I think your original jQuery code wasn't correct either. You need to do more research into this iftt.com platform and how to use it. From what I can tell, it's meant to be used in a mobile app, not in the browser- it would be a normal POST XHR then, and CORS doesn't apply to mobile apps. They have this page for testing the endpoint- notice that it gives you an example using curl, a command-line tool, where again CORS doesn't apply. So I think you need to rethink things, this service is not designed to be used from a browser, like you are trying to do.
EDIT: since it turns out you are actually trying to use JSONP and not a plain XHR, all you need to do is implement that without jQuery- create a script tag with the server's URL and add a URL parameter to define your callback function to handle the data. This answer should give you the solution.
In your case the code might look like this :
http://www.codeply.com/go/bp/VRCwId81Vr
function foo(data)
{
// do stuff with JSON
console.log(data)
}
var script = document.createElement('script');
script.src = "https://maker.ifttt.com/trigger/defender_send_message/with/key/"+
"dJdJekCVAFIqvUJ13DEczZjgIh_4MyeIGEHz2GBYKFe?callback=foo";
document.getElementsByTagName('head')[0].appendChild(script);
Note that this doesn't work for me(but with your code, you would get Message sent printed to the console, so maybe you thought it was working?)- the response isn't JSON. Most likely the endpoint isn't actually meant to be used for JSONP?
My answer below only applies if you are trying to do a regular XHR in a browser without JSONP.
This happens because of the Cross Origin Resource Sharing policy of your browser. Your code is hosted at localhost, and it is trying to access a resource hosted at maker.ifttt.com through an XmlHttpRequest. In order to allow this to happen, the server at maker.ifttt.com would need to be configured to allow access from the localhost origin. Presumably you can not make that change as you don't control that server.
In your case, the best solution would be to make the request to maker.ifttt.com through your own server- CORS doesn't apply for server-to-server requests. Send the XmlHttpRequest to your server, take the data regarding the email from the request URL parameters, and then make the request to maker.ifttt.com using that data.
My calls to $.post are not working all over my code. I'm not sending the request to other domains and, actually, I'm doing everything localhosted. My localhost alias was automatically defined by the Mac OS X 10.8 as ramon.local and I'm requesting from http://ramon.local/linkebuy_0.7/resourceX to http://ramon.local/linkebuy_0.7/resourceY. There are no errors on Chrome's console.
The server side doesn't receive the request and I can check it by accessing directly from the browser (typing the URL).
It's not just one call that is not working, none of them are. They were all working days ago and I'm suspicious that I accidentally changed something on my local settings. What could it be?
Here's an example of what I'm facing:
$.post(
<<CORRECT URL INSIDE THE DOMAIN>>,
{},
function(response) {
console.log('THIS SHOULD BE PRINTED ON CONSOLE');
alert('THIS SHOULD BE POPPED UP');
}
);
I don't get the alert, neither the console message while running the code above. So I tried the following:
$.support.cors = true;
$.ajax({
url: "http://ramon.local/linkebuy_0.7",
dataType: "json",
type: "GET",
crossDomain: true,
success: function (data) {
console.log(data);
},
error: function (xhr, status, error) {
alert(error + " - " + status);
}
});
I just came with $.support.cors = true; and crossDomain: true to check if it was a cross domain issue. So I was alerted No Transport - error same way as before.
What can I do to solve that?
Thanks in advance.
Try this and see if you are getting any alert:
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.post("your url", function() {
alert("success");
}).success(function() {
alert("second success");
}).error(function() {
alert("error");
}).complete(function() {
alert("complete");
});
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function() {
alert("second complete");
});
Well, I solved the problem in a very strange way.
I deleted the JQuery file and downloaded it again, replacing the old one. Happens it worked out.
So, if you're:
Making AJAX requests that are not cross-domain;
Using JQuery for it (e.g. $.post, $.get, etc);
Getting No Transport AJAX error
Then re-download and replace you're JQuery source.
Else, if you're making cross-domain requests (not this case), then look for JSONP and try to set $.support.cors = true; at the beginning of you're code.
Thanks everyone for the comments and answers.
In fact, I have a JavaScript application (jQuery) that is sending a request to a Java function which is supposed to send back data (success case) to my ajax function.
In the success case, I go on with my application; in error case, I stop my procedures and display the error message to the user.
But when the Java code takes more than 5 minutes to send a response to my Ajax call, this one (ajax code) doesn't (work / respond / go on /) get any response anymore ...
I tried setting up a timeout limit to 600000 ms (so 10 minutes) but I still get the same problem (and ain't got any error messages or output, which could have been helping me).
So if anyone's got an idea on the source of this problem, I'd be grateful.
Here is some piece of code if it may make it clearer :
JSP
$(document).ready(function() {
/* performing some layout changes */
//
preValidationDisplay();
}
function preValidationDisplay() {
/* performing some layout changes */
setTimeout("getValidationResult()", 500);
}
function checkReadLogFile() {
$.ajax({
url: logFileUrl,
cache: false,
success: function(result)
{
$("#progressBarToResize").width(
'' + parseFloat(result.trim()) + '%' );
}
});
}
function getValidationResult()
{
var timer = setInterval("checkReadLogFile()", 1000);
$.ajax({
url: '<s:url value="doValidation"/>',
type: "GET",
cache: false,
dataType: "json",
async: true,
//timeout : 600000,
success: function(result, status)
{
// Do something
},
error: function(jqXHR, status, errorStr){
// Do something
}
});
}
java
#RequestMapping(value = "/doValidation", method = RequestMethod.GET)
public String processValidationResults(HttpServletRequest request, HttpServletResponse response,
#RequestHeader("Connection") String conn) {
ValidationResult validationResult = null;
JSONObject resultJson = new JSONObject();
HttpSession session = request.getSession();
JSONObject progressMap = (JSONObject) session.getAttribute("progressMap");
String uploadedFilePath = progressMap.getString("filePath");
String realMimeType = progressMap.getString("realMimeType");
long fileSize = progressMap.getLong("fileSize");
String ctxPath = request.getContextPath();
// INVOKE the VALIDATION ENGINE
try {
validationResult = validationEngineService.getValidationResult(uploadedFilePath, ctxPath);
resultJson = JSONObject.fromObject(validationResult);
} catch (Exception e) {
validationResult = null;
resultJson.put("errorMsg", e.toString());
}
try {
response.getWriter().print(resultJson);
response.flushBuffer();
} catch (Exception e) {
}
return null;
}
When you're working with HTTP, never expect a connection to take longer than half a minute.
Either use WebSockets or Comet (long polling).
See, there are many parties that might decide to stop your connection:
web browser, firewall/router/isp, web server (eg: Apache), server scripting language (eg: PHP)
The only time I disable this on the PHP side is when I want PHP to keep running even after the user stopped the connection (which, by the way, I have enable yet another setting).
Without some code, i'm not sure if i could help much but have you tried checking which event is triggering the ajax call? I made a silly mistake once by sending an ajax request on keydown, i later found out that instead of keydown , i needed to use keyup since thats the event triggered once the value of the textbox is set to the text + key recently entered.
So you could try a keyup or change the event in jQuery. If this is on localhost, its not a good sign....first determine whats causing the problem, the frontend or backend.
Things to do:
1) Change event type in jQuery
$("#elem").live("keyup",function() {//send req});
2) Check apache log. If your on ubuntu or something similar, you can go to /var/log/apache2/error.log
I am making a JSONP request in a chrome extension (content script) . Everything works very well when I am running as a webpage -loading the HTML file in my browser-, but when I load it as a chrome extension, the jsonp callback function created by jquery doesn't seem to exist when the server gives its response.
My console says:
Uncaught ReferenceError: jQuery17105683612572029233_1323808231542 is not defined
Here is my ajax request:
$.ajax({
url: 'http://example.com',
data:
{
imgUrl: this.href,
returnString:true
},
dataType: "jsonp",
success: function(msg){
newNode.src = msg.data;
},
error: function(msg){
console.log(msg.data);
}
})
The issue is that the JSONP response is being caught by the actual page, outside of the sandboxed JavaScript code that the Chrome content script limits you too.
jQuery17105683612572029233_1323808231542 is the name of the callback function that the jQuery JSONP call has dynamically generated for the specific call. This function is being defined in the sandboxed area the content script has access to.
The only workaround that I am aware of, which worked for me, is to make an XHR call from the content script. As of Chrome 13 you can make XHR calls cross-domain from the content scripts (pretty cool). In your manifest file you need to add the external URL to the permissions:
{
...
"permissions": [
"http://example.com"
]
}
You can then make the XHR call like so:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com/", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
//handle the xhr response here
}
}
xhr.send();
You will need to do some of the things that jQuery was doing automatically for you, like encoding the values of the data object into the XHR URL (in your case the "imrUrl" and "returnString") as well as convert the response from the xhr.responeText or xhr.reponseXML into an object.
The downside of this approach is that if you are sharing this code between a Chrome extension and something else (like a bookmarklet) you now have to have different logic for the Chrome use case.
For more info see: Chrome Extension XHR