2

I know there are many, many answers to this question on SO, but I haven't been able to find one that applies in this case. I'm making an asynchronous call to a Google service and need to return the result:

function getCustomPanorama(pano,zoom,tileX,tileY) {
    client.getPanoramaById(pano, function(result, status) {
        return {
            location: result.location,
            links: result.links,
            copyright: result.copyright+' BUT GREY',
            tiles: {
                tileSize: result.tiles.tileSize,
                worldSize: result.tiles.worldSize,
                centerHeading: result.tiles.centerHeading,
                getTileUrl: getCustomPanoramaTileUrl
                }
            };
        });
    }

I understand that the above is wrong and will not return, and think I need to use callbacks, but I don't understand where. Note that I can't change what is passed to getCustomPanorama. All help gratefully received.

UPDATE: Full code:

var panorama;
var client;

$(document).ready(function() {
    var panoramaOptions = {
        position: new google.maps.LatLng(51.52241608253253, -0.10488510131835938),
        panoProvider: getCustomPanorama
        };
    client = new google.maps.StreetViewService();
    panorama = new google.maps.StreetViewPanorama(document.getElementById("pano"), panoramaOptions);
    });

function getCustomPanorama(pano,zoom,tileX,tileY) {
    client.getPanoramaById(pano, function(result, status) {
        return {
            location: result.location,
            links: result.links,
            copyright: result.copyright+' BUT GREY',
            tiles: {
                tileSize: result.tiles.tileSize,
                worldSize: result.tiles.worldSize,
                centerHeading: result.tiles.centerHeading,
                getTileUrl: getCustomPanoramaTileUrl
                }
            };
        });
    }

UPDATE 2:

Suggestions are definitely that I'm trying to do something impossible, so trying another approach involving pre-caching the getPanoramaByID() responses.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
stml
  • 133
  • 1
  • 11

2 Answers2

2

Change getCustomPanorama to take an extra parameter for the callback and pass in a function that does what you needed to do with the result:

function getCustomPanorama(pano,zoom,tileX,tileY,callback) {
    client.getPanoramaById(pano, function(result, status) {
        var data = {
          location: result.location,
          links: result.links,
          copyright: result.copyright+' BUT GREY',
          tiles: {
              tileSize: result.tiles.tileSize,
              worldSize: result.tiles.worldSize,
              centerHeading: result.tiles.centerHeading,
              getTileUrl: getCustomPanoramaTileUrl
          }
        };
        callback(data); // call the function and pass in the data you would have returned
    });
}

getCustomPanorama(pano,zoom,tileX,tileY,function(data) {
    // do something with the results of the asynchronous call here        
});
Richard Dalton
  • 35,513
  • 6
  • 73
  • 91
  • Thanks Richard but that's the problem - I can't edit what's passed to getCustomPanorama because it's a function that's called from within Google's Maps API. – stml Feb 16 '12 at 12:00
  • @stml So is it the google maps API that does something with the data you are passing back? Is there a function you can call yourself and pass in the data? – Richard Dalton Feb 16 '12 at 12:04
  • I've updated with the full code above so you can see how it's called. I've tried modifying the call, but it doesn't work... – stml Feb 16 '12 at 12:40
2

panoProvider is not supposed to be called asynchronously. That means you have to have all necessary information for creating custom StreetViewPanoramas pre-populated.

But if you really need to call client.getPanoramaById inside of panoProvider then there is a very dirty trick:

function getCustomPanorama(pano,zoom,tileX,tileY) {
  var resultFromAsyncCall;
  client.getPanoramaById(pano, function(result, status) {
    resultFromAsyncCall = {
        ...
        copyright: result.copyright+' BUT GREY',
        tiles: {
          ... 
          getTileUrl: getCustomPanoramaTileUrl
        }
    };
  });

  while (!resultFromAsyncCall) {
    //wait for result
  }   
  return resultFromAsyncCall;
}

BUT, I discourage you from using this solution. Better try to re-think logic of your application.

Related question: Call An Asynchronous Javascript Function Synchronously

Community
  • 1
  • 1
yatskevich
  • 2,085
  • 16
  • 25
  • `client.getPanoramaById` is the method which is provided by Google Maps API. But `getCustomPanorama()` seems to be under your control. – yatskevich Feb 16 '12 at 12:13
  • getCustomPanorama() is called within another Google function, defining a custom Street View panorama. – stml Feb 16 '12 at 12:15
  • Could you please post the code which is calling your `getCustomPanorama()`? – yatskevich Feb 16 '12 at 12:19
  • Thanks - understand this solution but it's definitely not workable. I know I'm doing something unexpected though, so appreciate there may be no good answer... – stml Feb 16 '12 at 13:09
  • @yatskevich - do You have a working jsFiddle with your answer? – ragulka Apr 08 '13 at 14:31