Occasionally, an ajax request to Flickr's api will fail. I'm not sure if I'm doing something wrong here - or if I'm just not handling things correctly - but the code works over 90% of the time. When it doesn't work, I get the following error message from Firefox's console:
TypeError: jQuery19109306644694293944_1362865216185 is not a function
(I am letting jquery generate the callback, which is why the callback is named like that.)
This is the code that sometimes fails:
function getAppropriateSize(photo){
console.log("In getAppropriateSize");
/** stuff. query is defined here **/
$.ajax({
url: 'http://api.flickr.com/services/rest/?method=flickr.photos.getSizes&format=json&api_key='+flickrKey+'&photo_id='+query.id,
dataType:'jsonp',
jsonp:'jsoncallback',
timeout:3000,
success: function(sizes){
console.log("In success - getAppropriateSize");
/**determine the correct size**/
flickrURL = sizes.sizes.size[currVal].source;
},
error: function(xmlhttprequest,textstatus,msg){
console.log("In error - getAppropriateSize");
/* handle error*/
}
});
}
I've checked what's returned when this happens and JSLint says it's valid javascript. flickrURL also gets set to a valid URL. I'm pretty mystified about what's causing this error - any help would be appreciated.
Edit: I was messing around and this time getAppropriateSize just received two separate messages from flickr for one call. The first one was
({stat:"fail", code:1, message:"Photo not found"})
The second one was the a full response from the server that also produced the TypeError mentioned above. However, the second response found the photo and gave me the sizes.
Related
I have a chrome extension that calls out to a server Back End. It works fine when I have the back end adress hardcoded into the code, but whilst trying to move that out into a user configurable setting it fails. The problem appears to be AJAX's async behaviour causing the issue because JQuery is sending off the AJAX 'GET' request before the code reaches into the Chrome Storage to get the current setting.
Within a Chrome Extension (popup.js)
Using AJAX 3.5.1
The AJAX call is very simple:
$.ajax({
url: getCrumbURL(),
type: 'get',
data: {},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log("Status: " + textStatus);
console.log("Error: " + errorThrown);} ,
success: function (data) {
console.log(data);}});
and the getCrumbURL function is this:
function getCrumbURL(){
var myBackend;
chrome.storage.sync.get({ "backEndServerURL": 'Not set yet' }, function (result) {
myBackend = "http://" + result.backEndServerURL + "crumbIssuer/api/json";
console.log("1. Requesting crumb from: " + myBackend);
})
console.log("2. Requesting crumb from: " + myBackend);
return myBackend;
}
The AJAX function calls its own page (which I believe is the default if the url: is not set) so I think it's failing because it's not waiting for the call to chrome.storage.sync.get before trying to send the AJAX call. I suspect this because when I look at the output on the console, by two debus messages arrive in the reverse order:
Requesting crumb from: undefined
Requesting crumb from: http://192.168.99.100:8080/crumbIssuer/api/json
I know AJAX is Async, but this is from WITHIN the AJAX call (as opposed to elsewhere in the code).
Can anyone explain whether my assumption is correct and whether there's a way to force the AJAX to wait for the chrome.storage.sync.get to return it's value (as it provides the URL!).
Many thanks
Matt
EDIT 1: I have read a number of SO questions that explain how to work with a response from an Aysnc call (for example using a Promise) but (and this may be my lack of experience) I cannot see how this applies here. The issue is not trying to do something AFTER an ASync call (the $.AJAX) but BEFORE it takes place (so that it has the URL pulled from the Chrome Storage). If I'm missing the answer in the other SO questions, please could someone help me out by explaining how this would work in the situation posted above? Many thanks.
I'm using the Yummly API (https://developer.yummly.com/documentation) and I am trying to parse a JSONP list of courses to use in a drop-down box. The format of the file I am requesting (located at http://api.yummly.com/v1/api/metadata/course?_app_id=[My App ID]&_app_key=[My App Key]) is:
set_metadata('course', [{"id":"course-Main Dishes","type":"course","description":"Main Dishes","searchValue":"course^course-Main Dishes"},....................}])
The request seems to work fine, and I can view the results in the Network tab in Chrome. However, in the console I get the error "Uncaught ReferenceError: set_metadata is not defined" I've done a lot of looking around, and have found people with similar but different errors, but I have not understood the cause or why the fixes for their errors work. I am fairly new to jQuery, so I'm guessing I'm doing something wrong with my request, which is:
var coursesURL = 'http://api.yummly.com/v1/api/metadata/course?_app_id=' + appID + '&_app_key=' + appKey;
var courses = [];
//Query for the list
$.getJSON(coursesURL + '?callback=?', null, function(data) {
console.log(data);
//Go through each result object found
$.each(data.course, function(i, course) {
courses.push(course.description);
});
console.log(courses);
});
Any help is greatly appreciated. I would also really appreciate an explanation of what I am missing, not just the fix. Thank you.
The reasons I'm adding this as an answer and not a comment are because i don't have enough reputation to comment and this is the only thing i can find on the yummly api returning jsonp.
I was able to get past the "uncaught referenceError" problem but now its only returning the word 'allergy', which is in the response, and I'm not getting the rest of the data.
here is my code:
$.ajax({
url:"//api.yummly.com/v1/api/metadata/allergy?_app_id=[APP_ID]&_app_key=[APP_KEY]?callback=",
dataType:"jsonp",
jsonpCallback:"set_metadata",
beforeSend:function(){
console.log("sending");
},
success: function (data){
console.log(data);
},
error: function(data){
console.log("send error and returned:");
console.log(data);
}
});
here is the response:
set_metadata('allergy', [
{"id":"392","shortDescription":"Wheat-Free","longDescription":"Wheat-Free","searchValue":"392^Wheat-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"393","shortDescription":"Gluten-Free","longDescription":"Gluten-Free","searchValue":"393^Gluten-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"394","shortDescription":"Peanut-Free","longDescription":"Peanut-Free","searchValue":"394^Peanut-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"395","shortDescription":"Tree Nut-Free","longDescription":"Tree Nut-Free","searchValue":"395^Tree Nut-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"396","shortDescription":"Dairy-Free","longDescription":"Dairy-Free","searchValue":"396^Dairy-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"397","shortDescription":"Egg-Free","longDescription":"Egg-Free","searchValue":"397^Egg-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"398","shortDescription":"Seafood-Free","longDescription":"Seafood-Free","searchValue":"398^Seafood-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"399","shortDescription":"Sesame-Free","longDescription":"Sesame-Free","searchValue":"399^Sesame-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"400","shortDescription":"Soy-Free","longDescription":"Soy-Free","searchValue":"400^Soy-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]},
{"id":"401","shortDescription":"Sulfite-Free","longDescription":"Sulfite-Free","searchValue":"401^Sulfite-Free","type":"allergy","localesAvailableIn":["en-US","en-GB"]}
]);
the line of code that says:
jsonpCallback:"set_metadata",
in the ajax call gets me past the reference error but im not getting the rest of the data that's in the response.
please help?
Finbar
I figured out the problem.
JSONP is returning not JSON text, but a function to the callback. Thus, I needed a function in my code called "set_metadata" that is used upon success of the json/ajax call.
Specifically, I defined function
function set_metadata(course, data) {
//Do stuff here
};
I tested it and that correctly captures the data I am trying to get.
I've got the following code to call a json web service in a separate functions.js file.
function getMajorGroups(){
var element = $(".item-group-button");
$.ajax({
type:"GET",
url:"localhost:6458/posApplication/getAllMajorGroups",
data:"{}",
contentType:"application/json; charset=utf-8",
dataType:"json",
done:successResult(majorGroups),
fail:errorResult(error)
});
}
function successResult(majorGroups){
var mGroups = response.d;
$("#item-groups").empty();
$.each(majorGroups ,function(){
var h3 = $('h3').append(majorGroups.code);
element.append(h3);
$("#item-groups").prepend(element);
});
}
function errorResult(error){
alert("error");
}
When I run the web page and I use firebug to trace the steps I can see the script is executed. But it does not execute the success or failure code inside the ajax call. Am I doing anything wrong here?
Below is an example of the string which the service return.
{"majorGroups":[{"update":"false","hasMore":"false","status":"A","description":"Beverage","majorGroupId":"48","code":"Beverage"},{"update":"false","hasMore":"false","status":"A","description":"Laundry","majorGroupId":"51","code":"Laundry"},{"update":"false","hasMore":"false","status":"A","description":"Cigarette","majorGroupId":"50","code":"Cigarette"},{"update":"false","hasMore":"false","status":"A","description":"Food","majorGroupId":"47","code":"Food"},{"update":"false","hasMore":"false","status":"A","description":"Health Center","majorGroupId":"52","code":"Health Center"}],"failure":"false"}
$.ajax has no property named failoure. error should be used so it looks like error: errorResult
Besides that check that request is made via Network tab in Chrome dev tools or some similar tool. Check what is in the the raw response and make sure that is what you wanted. If request failed you will see way or at least have error code.
If everything is fine so far then make sure your adding DOM elements when DOM is ready so wrap your stuff with $(function(){ /* your stuff here */ })
Edit:
That's not the way done and fail should be used. jQuery ajax call returns promise.
$.ajax({
url : "..."
/* omitted */
}).done(successCallback).fail(failCallback)
where successCallback can be either function name like your defined succes function or just anonymous function like
.done(function(response){
// do stuff with response
}
I think you should carefully read jQuery documentation.
Also your $.each call is kinda broken - you skipped parameter in function provided to $.each
In CRM Dynamics I'm executing the following code. I've tried to put it inside a try-catch statement to catch the allegedly uncaught exception but it makes no difference. I'm guessing that it occurs inside CRM server, C# code or something like that.
var temp = OData.read({
urlOrRequest: "https://myurl/2011/OrganizationData.svc/crmk_CustomEntitySet",
success: function(dataSet) { alert("Yippi!"); },
error: function(errorMessage) { alert("Buuuu..."); },
handler: null,
httpClient: null,
metaData: null
});
Of course, I've tested to execute the https://myurl/2011/OrganizationData.svc/crmk_CustomEntitySet call and it resturns the data as supposed to, so apparently I've got connection and access right in order.
However, I get neither of the callbacks to execute. Everything is just ghostly quiet. As I attempt to close or reload the page, though, I get an error message from CRM Dynamics, the partial contents of which are listed below.
<ScriptErrorDetails>
<Message>Exception thrown and not caught</Message>
<Line>13</Line>
<URL>/%7B634854498230000000%7D/WebResources/crmk_MyResourceWithDataJS</URL>
<PageURL>/userdefined/edit.aspx
?etc=10008&pagemode=iframe&preloadcache=1349853066209</PageURL>
<Function></Function>
<CallStack></CallStack>
</ScriptErrorDetails>
Given my competence level with CRM Dynamics (low) and with DataJS package (loooow), I'm stuck having no clue as to why it doesn't work nor how to trouble-shoot it.
I've checked out every example I could find on their page
You're getting no callback execution because you're not sending in one. You think you do but you don't. You're using the JSON syntax putting the properties (or whatever they're called) in an object. You're intending the following list of inputs.
The URL to organization data.
A function telling what to do if successful.
A function telling what to do if failed.
A bunch of nulls.
But since you package it into a structure, the CRM sees the following (regarding the full signature of the function odata.read(...) as seen in the source file..
An object with some stuff in it, not constituting a parsable URL.
Nothing at all, meaning null, while CRM wants to see a function (success).
Nothing at all, meaning null, while CRM wants to see a function (fail).
Nothing at all, meaning null, while CRM wants to see a function (serialization).
Nothing at all, meaning null, while CRM wants to see a HTTP client layer (whatever that might be).
Nothing at all, meaning null, while CRM wants to see some metadata.
Then a crash occurs inside the CRM server (since you failed to provide a parsable URL to the organization data that you're trying to read) and an exception is being thrown. But you haven't provided a callback function for receiving the notification of such an error, which is the message you've mentioned.
Your try-catch doesn't catch anything since there's no exception to catch. It's already been caught inside CRM Dynamics server. What you see is that it complains that there's no function to be called for notifying you about that.
Try to execute an equivalent to this code and see if you're successful (or at least get another error message).
var temp = OData.read(
"https://myurl/2011/OrganizationData.svc/crmk_CustomEntitySet",
function(dataSet) { alert("Data retrieval successful."); },
function(errorMessage) { alert("Operation failure!"); }
});
I'm assuming that you're using an other URL than what you've shown us in your code sample. It's just an example, right? You can test pasting in the very URL into IE and see if you'll get a reply and what it contains.
Basically just looking to see if a particular txt file exists on the server, and if so, do further processing; however, I don't think my recursion is correct, so can someone offer a few pointers - here's what I have:
function fileExists(filename) {
$.ajax({
type: 'HEAD',
url: 'http://www.example.com/system/'+filename+'.txt',
success: function() {
// Further processing if file exists
},
error: function() {
// File does not exists, run through function again-
return arguments.callee(filename);
}
});
}
It's pretty basic, there's some processing before hand that actually creates the file; however the issue is it's FTP-ed up to our domain, which means timing can vary by a few seconds, so basically I just want it to recheck until it sees that the file exists. I'll modify it a little afterwards to control the stack, possibly setting a timeout of half a second or something, but I'm not that great with javascript, so I need a few pointers to make this recursive. Any help is GREATLY appreciated.
the issue is when you try to call fileExists again via arguments.callee(fileName), the scope of the error method isn't what you think it is.
Just call fileExists.
The other you are going to have is that if your server is quick, you are going to be firing a ton of requests. You probably want to wait some time between requests. So make error contain
setTimeout(function(){
console.log('trying again....'); // this won't work in IE, I *think*
fileExists(filename);
}, 1000); // try again in a second
Finally, you should realize that the error callback only gets invoked if the server returns a 500. The 500 code usually means there was an error on your server. If a file doesn't exist, you should probably return json to indicate the file doesn't exist, and handle that case in your success callback.
error: function() {
fileExists(filename);
}