AJAX silently failing when loading script - javascript

I just notice a weird behavior when dynamically loading scripts with AJAX.
I intentionally have a misspelled code that throws an error when it is parsed. Even though the Chrome's console indeed shows the error, the AJAX fail handler is never called.
This is the function that I use to load files:
var load_source = function (path) {
/* Variable used to determine whether the request was successful */
var success = false,
failed;
$.ajax(
{
url: path,
async: false,
dataType: 'script',
method: 'GET'
}
).
done(function () {
success = true;
}).
fail(function (xhr, status, error) {
failed = error.stack ? error.stack : error;
});
if (failed)
{
throw new Error('Unable to load JS file {0}: {1}'.format(path, failed));
}
}
The only variable provided to the load_source function is "path", which value is a string with the location and name of such a file: "js/myFile.js".
The misspelled part (the part with a typo) of the script to load is this:
var f = function (arg) {
var param1 = 3,
param2, /* NOTICE the typo: there is a comma instead of a semicolon */
if (param1 > arg)
{
return true;
}
// And more code is coming next...
If I look at the Chrome's console, it shows the error:
Uncaught SyntaxError: Unexpected token if
So far the only way I can catch the error is with the window's onerror event.
So, if that is the only way to catch the error, could you tell me how to stop the "coding" flow, I mean, whenever I call load_source that throws an error (which is handled by the window's onerror function) I want the script to do nothing else:
load_source('js/myFile.js'); // This script will throw the "Uncaught SyntaxError: Unexpected token if" error.
// So I don't want the following code to be executed.
sum(4, 3);
mul(5, 5);
// ...
Can you guys tell me how make the fail event to be triggered?
I also tried with " $(document).ajaxError" but with the same results.

It's async stuff :) There is no way that the resource fetching (load_source(url)) is going to be finished before your sum() and mul() functions are executed.
The things you want to make dependable on the successful loading of your remote resource, should be placed in a callback, which is executed after success of the resource fetching.
UPDATE
Regarding the "aysnc: false" in your example, and mentioned in the
comments: this applies only to the $.ajax() function scope, not to
the parent function.
Also: is_empty is not part of the standard
library, I assume you have defined that function elsewhere?

The fail event is being triggered, it's just not stopping the rest of the JS from running. You'd be better off doing some thing like this:
if(load_source('js/myFile.js'))
{
sum(4, 3);
mul(5, 5);
}
Then removing your throw in your load_source() function and using return success;, like so:
var load_source = function (path) {
/* Variable used to determine whether the request was successful */
var success = false;
$.ajax(
{
url: path,
async: false,
dataType: 'script',
method: 'GET',
success: function(){
success = true;
},
error: function (xhr, status, error) {
console.log(error.stack ? error.stack : error);
}
}
);
return success;
}

Related

JQuery autocomplete function causing reference error

I am using jquery auto complete functionality. But occasionally I get Reference error:function is undefined in IE but works in Chrome.
This is my code which calls a backend Java function.
jQuery('autocomplete').focus(function() {
var f = jQuery(this);
f.autocomplete({
minLength: 3,
source: function(request, response) {
var etype = jQuery("#type").val();
Util.getId(
function(data) {
if (!isUserSessionValid(data[0])) {
return;
}
response(exportRespToArray(data));
},
etype,
f.val(),
getLang()
);
}
});
});
Util.getId() is a backend java function that returns data back. On success, the code checks if user session is still valid, if not forward to login screen.
But occasionally IE displays reference error that exportRespToArray is undefined. Both the functions are clearly defined in the external js file which is imported into the jsp. The autocomplete function is initialized through document.ready function.
It's legacy code and I am no jQuery expert. I guess the success keyword inside the Util.getId() function is optional? Why do I get the reference error only in IE if the call was success?
Ok. Did some research and function(data) is a DWR callback function.I could probably add an errorHandler block to find out if any error is returned from server.
Util.getId(
etype,
f.val(),
getLang(), {
callback:function(data) {
if (!isUserSessionValid(data[0])) {
return; }
response(exportRespToArray(data));
},
errorHandler:function(message) {
alert("Error returned: " + message);
}
});

Uncaught TypeError: Cannot read property 'results' of undefined

I'm a complete newby to JS. Trying to use SharePoint REST API to display a link list in a footer. Keep getting this error no matter what I do. It is for this line LoadFooterLinks(results.d.results);
function GetFooterLinks() {
var url = _spPageContextInfo.siteAbsoluteUrl + "/_api/lists/getbytitle('Footer Links')/items/?$orderby=Display_x0020_on_x0020_Homepage";
$.ajax({
url: url,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function (results) {
LoadFooterLinks(results.d.results);
},
error: function (error) {
console.log("Error in getting List: " + listName);
}
});
}
A few things:
How do you know you have an "error"?
Is is a Javascript Exception?
WHAT IS the error or Exception?
How do you know the error isn't with your LoadFooterLinks() function?
Most likely your results are NOT what you are expecting. You're obviously:
Successfully making a connection and request
But, you can't be sure what's coming back. It could be:
empty string
null
malformed
Hitting F12 in most browsers will bring up that browser's Developer mode/built-in JS console
My code changes below should help you debug by outputting to the console for you.
Things to NOTE about the code changes:
The difference between:
catching a JavaScript runtime exception/error using try-catch vs.
outputting the string variable arbitrarily named "error" in the failure callback method of the $.ajax object
Print an exception to to the console doesn't require console.err()
If you want to show a string as an error in the console use console.err(), not console.log.
Null is an object, not a datatype or primitive like the other ones in JavaScript. For Example,
boolean
string
undefined
number
New Code
function GetFooterLinks() {
var url = _spPageContextInfo.siteAbsoluteUrl +
"/_api/lists/getbytitle('Footer Links')/items/?
$orderby=Display_x0020_on_x0020_Homepage"
;
$.ajax({
url: url,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function (results) {
if (!results) { // should handle null and empty strings
try{
LoadFooterLinks(results.d.results);
}
catch (e){ // catch any JavaScript runtime exception (error)
console.log(e); // print the error to the console
// (hit F12 in most browsers to see
// the console BEFORE you refresh
// the page to run your code)
}
}
else {
var msg = "The 'results' variable is ";
var varType = typeof(results);
if (varType == "object") {
msg += "NULL";
}
else {
msg += varType;
}
}
},
error: function (error) {
// this 'error' variable can be named
// anything you'd like and is a string
// description of the AJAX error.
// This description comes from $.ajax -
// which is part of jQuery (a JS library).
// This "error" is not a native JS
// exception; therefore, you wouldn't
// use a TRY-CATCH. Also, since it's
// only a string, if you want to show it
// as an error in the console, you should
// use `console.err`, not `console.log`.
console.err("Error in getting List: (0)", error);
}
});
}
What you are basically doing is making a request to the "/_api/lists/getbytitle" method.
When that method returns a response, it will do so as an object named "results", as you can see under the "success" callback.
What you are doing afterwards is reading a property called "d" and within "d" you are trying to obtain the value of property called "results".
What the error is saying is that "d" is undefined therefore it cannot retrieve the value of "results" from "d".
I suggest you check what is inside the object "results" of the success callback.
For SharePoint API result, you would need to parse the JSON response to convert it to Javascript object. I've modified your code a bit to make it work in this case.
function GetFooterLinks() {
var url = _spPageContextInfo.siteAbsoluteUrl + "/_api/lists/getbytitle('Footer Links')/items/?$orderby=Display_x0020_on_x0020_Homepage";
$.ajax({
url: url,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function (response) {
var svcData = JSON.parse(response.data).d.results;
LoadFooterLinks(svcData);
},
error: function (error) {
console.log("Error in getting List: " + listName);
}
});
}

Parse javascript count method on queries

In Parse's javascript API, does the count method not do anything if no objects are returned? I'm trying to query for a new table I just added, and I can't seem to get a query to return results.
var contactObj = Parse.Object.extend("Contact");
var contactQuery = new Parse.Query(contactObj);
contactQuery.equalTo("phone", req.body.From);
contactQuery.count({
success: function(number) {
// There are number instances of MyClass.
console.log("something");
},
error: function(error) {
// error is an instance of Parse.Error.
console.log("error");
}
});
In this code, when run, no console.logs are received, but the enclosing method that I call does print that it has been run. Does count not get to success OR failure if the count is 0?
Your are missing the response.success and response.error calls, but console logs are still writing.
See below
Your exact piece of code is returning in your workstation console "success/error was not called" when running.
But still in parse portal console you see "something" output...
Output parse console in your local machine:
{"code":141,"error":"success/error was not called"}
Output parse portal in Logs
Failed with: success/error was not called
I2015-01-14T09:28:26.174Z] something
I'd added below two lines:
response.success("something success");
response.error("something error");
so actual code will be like the one below:
Parse.Cloud.define("StackOverflowTesting", function(request, response) {
var contactObj = Parse.Object.extend("Contact");
var contactQuery = new Parse.Query(contactObj);
contactQuery.equalTo("phone", req.body.From);
contactQuery.count({
success: function(number) {
// There are number instances of MyClass.
console.log("something success console");
response.success("something success");
},
error: function(error) {
// error is an instance of Parse.Error.
console.log("something error console");
response.error("something error");
}
});
});
outputs
workstation console:
{"result":"something success"}
Parse portal Log:
Result: something success
I2015-01-14T09:29:54.355Z] something success console
I had a similar issue where console.logs were not called from success and error blocks. This was caused due to an infinite while loop after the query. Something of this kind -
var c = 0;
var query = new Parse.Query("XXXXX");
query.equalTo("YYYY","abc");
query.count({
success: function(count) {
c += 1;
console.log("success");
},
error: function(error) {
c += 1;
console.log("failure");
}
});
while (c < 1){
}
..........
Node.js is asynchronous but it's also single-threaded. Make sure you do not have any such code blocks which are holding up the execution.
Also, query.count gets to success even if the no. of results is 0.

refrer function name in ajax, reverse callback on fail

I have no idea how I can achieve this.
I am using jQuery 1.9 for ajax call back.
I have a function, let's say:
function a (param){
//calling a function this will perform ajax
data = performAjax(param, url, etc);
// render response
renderResponse(data);
}
We are executing our ajax in perform ajax function.
Issue is when ajax fails then it perform ajaxError function.
I put a message in div that please refresh this again.
But how can I get function a and all the parameter of that in ajaxError function? So that I can put a link to refresh again.
Not sure if I understand correctly, but here it goes:
function performAjax() {
return $.ajax({
....
});
}
var lastFailedFunction;
function a (param){
var args = arguments;
//calling a function this will perform ajax
performAjax().then(function(data) { // on success
// render reponse
renderResponse(data);
}, function() { // on failure
lastFailedFunction = function() {
a.apply(a, args);
};
// now you can call lastFailedFunction() to try again
});
}
When the ajax-call fails, it will store the failed function call to lastFailedFunction. So somewhere else you might show this message:
<div>Function A failed, click here to try again</div>
Using error callback of ajax, you can get the error message
function a(param) {
var performAjax = $.ajax({
type: "",
url: "",
data: "",
success: function(msg){
//success msg
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
//can access param of fun a and the error message
//append it to the body
$('body').append('<div>'+param+' error: '+errorThrown+'</div>');
}
});
}

Jquery Ajax/getJSON Javascript Question

I am still trying to figure all this out and I am coming across a really weird error.
I was using getJSON but after searching for solutions to this problem, I found that it was better to try to use the AJAX function (for error capturing -> which isnt firing).
Using breakpoints in firebug, if I go slowly through the running code, it works (mostly) fine (just need to change some coordinates for better drawing). But if I let it run at normal speed, it attempts to do the callback before the json object is returned. The firebug console says everything works ok (code 200), but when examining the jobj inside ship object/function it appears to be "undefined or null"
Following the breakpoints, the ajax calls seem to be going to "error" and not "success". But it isn't firing the alert...
Also, the response takes like 300-500ms.... is that normal? or do I need to find a better server?
Edited Code:
var init = (function(){
thisplayer = new player();
jQuery.ajax({type: "GET", url: "shipdata.php", processData: true, data: {shipid:1}, dataType: "json",
success: function(json) {
var pship = new ship(json);
player_ship = $.extend(thisplayer, pship);
starfield = new starfield();
for(var i = 0; i < player_ship.enemytotal; i++) {
$.ajax({
type: "GET",
url: "shipdata.php",
processData: true,
data: {shipid:Math.round((Math.random()*2+2))},
dataType: "json",
success: function(json) {
var enemy = new ship(json);
game.enemies.push(enemy);
},
error: function(x,y,z) {
// x.responseText should have what's wrong
alert(x.responseTest);
}
});
}
game.initialized = true;
},
error: function(x,y,z) {
// x.responseText should have what's wrong
alert(x.responseTest);
}
});
})
..............................
var ship = (function(json){
var self = this;
jobj = jQuery.parseJSON(json.responseText);
self.height = jobj.height;
self.width = jobj.width;
self.xinit = jobj.xinit;
self.yinit = jobj.yinit;
self.speed = jobj.speed;
self.weapons = jobj.weapons;
self.maxlasers = jobj.maxlasers;
self.imagesrc = jobj.imgurl;
self.lasers = [];
self.x = self.xinit;
self.y = self.yinit;
JSON being sent in:
{"height":75,"width":50,"xinit":275,"yinit":525,"speed":3,"weapons":[1,2],"maxlasers":2,"imgurl":"images\/ship.png"}
Live Demo:
http://www.schennshome.net/medicalmmj/practice/index.html (The code is far from being perfect, Im running through it to try and catch the various errors before animating, but cant get past this.)
I've dug through your source code, and the problem is not actually shown in your question. The problem is with this line, which follows your Ajax call:
player_ship = $.extend(thisplayer, game.pship);
game.pship refers to the data returned by the ajax call, but since this is asynchronous, the above line will be evaluated first, which means game.pship will not be defined.
To fix this, you need to include all of the code in your init function that is currently below the ajax call directly in the success callback. This will prevent the code from being evaluated until the ajax call has returned.
The reason that it works with breakpoints is that this interrupts evaluation, which allows the ajax call to complete before game.pship is referenced.
Edit
I'm now getting an error on line 489, stating that player_ship is undefined. This is again because of the evaluation order of async code. The problem is that player_ship is being defined inside the ajax function in init now, but is being referenced in gameLoop, outside of this callback.
This is how I would rewrite gameLoop:
var callback = function() {
game.canvas.clearCanvas();
drawStarfield();
if(player_ship.alive && game.initialized && !(game.loading)) {
drawPlayer();
drawLaser();
drawEnemies();
}
};
if(game.initialized==false) {
init(callback);
} else {
callback();
}
And then amend init to accept a callback method which is called at the bottom of your success callback. This way, if the game has not been initialized (and player_ship is not yet defined), it will be executed after the ajax call.

Categories