Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught TypeError: Property ... is not a function - after page has loaded

I'm using a cross-domain Ajax request to an external API. Every so often it fails, with the console message:

Uncaught TypeError: Property 'photos' of object [object DOMWindow] is not a function

Looking at the JSON being returned, it is valid JSON, so it is not the fault of the external API.

I can't reproduce the error reliably: the only factor that seems to trigger the error is when I call the request quickly and repeatedly.

In this case I'm calling the Ajax request when the user moves a Google map (to add markers to the map), and it occurs if the user moves around too quickly.

Here are the relevant parts of my code:

// Code located inside an external JS file referenced inside the head
// Not wrapped inside document.ready - but all the code setting up 
// the map (calling a function which calls a function which adds the 
// tilesloaded listener) *is* inside document.ready
function addMarkers() {
    var pm_url = "http://www.cyclestreets.net/api/photos.json?key=" + MY_KEY;
    $.ajax({
       url: pm_url,
       crossDomain: true, 
       contentType: "application/json",
       dataType: 'jsonp',
       data: pmdata,
       jsonpCallback: 'photos',
       success: function(data) {
        // TBA
       },
       error: function() {
           alert("Sorry, error retrieving photos!");
       }
   });
}
 google.maps.event.addListener(map, 'tilesloaded', function() {
 addMarkers(map);
 });

Having Googled a bit, the error Uncaught TypeError: Property 'photos' of object [object DOMWindow] is not a function generally seems to occur when jQuery has not been loaded.

However, I don't see that this is relevant here, because the function is called from the map's tilesloaded event - and it doesn't generally fire the first time, it tends to fire after five or six rapid map resizes. So if it works once, the page surely can't have 'forgotten' about jQuery?

Thanks for your advice.

like image 501
Richard Avatar asked Jul 01 '11 11:07

Richard


1 Answers

If you want to specify the name of the function that jQuery creates from your success handler, but not actually define a separate function to use, you should use jsonp: 'photos' instead of jsonpCallback: photos. Currently it's using photos in the URL which means it's calling photos({ ...data... }) when the JSONP response comes back, and that doesn't exist. Using the jsonp option on $.ajax() would create it. You have a few options here.

You can do this (in a global scope) either of these two ways:

function addMarkers() {
    var pm_url = "http://www.cyclestreets.net/api/photos.json?key=" + MY_KEY;
    $.ajax({
       url: pm_url,
       crossDomain: true, 
       contentType: "application/json",
       dataType: 'jsonp',
       data: pmdata,
       jsonpCallback: 'photos',
       error: function() {
           alert("Sorry, error retrieving photos!");
       }
   });
}
function photos(data) {
    // TBA
}

Or, what you intended I think:

function addMarkers() {
    var pm_url = "http://www.cyclestreets.net/api/photos.json?key=" + MY_KEY;
    $.ajax({
       url: pm_url,
       crossDomain: true, 
       contentType: "application/json",
       dataType: 'jsonp',
       data: pmdata,
       jsonp: 'photos',
       success: function(data) {
        // TBA
       },
       error: function() {
           alert("Sorry, error retrieving photos!");
       }
   });
}

....or just leave both off and let jQuery name the success callback itself (this happens by default, based on a timestamp).

like image 189
Nick Craver Avatar answered Nov 15 '22 00:11

Nick Craver