...

View Full Version : How to make sure a function completes before continuing execution.



kberry
07-20-2011, 06:16 AM
Hi,

I have a function that I'm trying to modify. It adds an element to the page. The problem is, I require that ClickGeocode() finishes executing before the rest of the code in the function completes. Currently that is not the case... Any ideas?


Event.add(window, 'load', function()
{
Event.add('addressSearch', 'click', function()
{
ClickGeocode();
var el = document.createElement('p');
el.innerHTML = "  " + addressSearchAddress + " : [" + addressSearchRadius + "]";
Dom.add(el, 'AddressesVisited');
Event.add(el, 'click', function(e)
{
Dom.remove(this);
});
});
});

xelawho
07-20-2011, 07:34 AM
I think the problem that you are having is that Geocoding is asynchronous
(a query is sent to the server and the callback function runs when the data comes back).

you should be putting the above code in the callback function, to ensure that the data has arrived from the server. From what you describe your code is running before the server has had a chance to reply.

kberry
07-22-2011, 11:51 PM
OK, I added the necessary code, however the whole asyncronous issue is still giving me grief. I click "Search" and GeocodeCallback zooms to the desired address and adds a pin like it should. However, I must click "Search" again in order for the n-1 address that I entered to show up where I want it to. Here's the code. It'd be nice to be able to have the address appear the first time I click "Search"... Any ideas?


function GeocodeCallback(result)
{
if(!(result.resourceSets[0].resources[0]==undefined))
{
//if the location is found by Bing
if (result && result.resourceSets && result.resourceSets.length > 0 && result.resourceSets[0].resources && result.resourceSets[0].resources.length > 0)
{
address_found=true;
//get the latitude/longitude of the address
address_pin_lat=result.resourceSets[0].resources[0].point.coordinates[0];
address_pin_lon=result.resourceSets[0].resources[0].point.coordinates[1];
addressSearchAddress = result.resourceSets[0].resources[0].name;
}
address_search_func();
add_visited_address();
}
else
alert("Please enter a valid address.");
}

function add_visited_address()
{
Event.add(window, 'load', function()
{
Event.add('addressSearch', 'click', function()
{
var el = document.createElement('p');
el.innerHTML = "&nbsp;&nbsp;" + addressSearchAddress + " : [" + addressSearchRadius + "]<br>";
Dom.add(el, 'AddressesVisited');
Event.add(el, 'click', function(e)
{
alert("Go to this address...");
// Dom.remove(this);
});
});
});
}

xelawho
07-23-2011, 02:31 AM
It'd be nice to be able to have the address appear the first time I click "Search"...
for sure. can you post a link to your page, or an example page showing the problem?

kberry
07-23-2011, 02:45 AM
Unfortunately I can't link you at this time, however what I'm trying to do is search for a Bing maps location, and add it to an element on the page as a list of addresses visited.

The Bing Maps code I modified (GeocodeCallback is the asyncronous function causing me grief): http://msdn.microsoft.com/en-us/library/gg427601.aspx

The Event.add code came from this site: http://www.dustindiaz.com/basement/add-remove.html

I combine the two approaches to give me what you see in my previous post.

xelawho
07-23-2011, 03:07 AM
hmmm... I can't see it. As a long shot you could try calling the add_visited_address function as soon as the result has been found, ie directly after this line:
addressSearchAddress = result.resourceSets[0].resources[0].name;.

otherwise, maybe you could post your entire code?

kberry
07-23-2011, 03:46 AM
Here's all the parts working together except for address_search_func since it's not relevant to the issue at hand. I'll work towards getting a sample combining the two things together.


//Adding a Visted Address
var Dom =
{
get: function(el)
{
if (typeof el === 'string')
return document.getElementById(el);
else
return el;
},
add: function(el, dest)
{
var el = this.get(el);
var dest = this.get(dest);
dest.appendChild(el);
},
remove: function(el)
{
var el = this.get(el);
el.parentNode.removeChild(el);
}
};

var Event =
{
add: function()
{
if (window.addEventListener)
return function(el, type, fn) { Dom.get(el).addEventListener(type, fn, false); };
else if (window.attachEvent)
{
return function(el, type, fn)
{
var f = function() { fn.call(Dom.get(el), window.event); };
Dom.get(el).attachEvent('on' + type, f);
};
}
}()
};

function add_visited_address()
{
Event.add(window, 'load', function()
{
Event.add('addressSearch', 'click', function()
{
var el = document.createElement('p');
el.innerHTML = "&nbsp;&nbsp;" + addressSearchAddress + " : [" + addressSearchRadius + "]<br>";
Dom.add(el, 'AddressesVisited');
Event.add(el, 'click', function(e)
{
alert("Go to this address...");
// Dom.remove(this);
});
});
});
}

function ClickGeocode() { map.getCredentials(MakeGeocodeRequest); }

function MakeGeocodeRequest(credentials)
{
var geocodeRequest = "http://dev.virtualearth.net/REST/v1/Locations/" + document.getElementById('address').value + "?output=json&jsonp=GeocodeCallback&key=" + credentials;
CallRestService(geocodeRequest);
}

//I believe this is done asyncronously. I need to make it synchronous.
function CallRestService(request)
{
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", request);
document.body.appendChild(script);
}

function displayaddressInfobox(e)
{
addressInfobox = new Microsoft.Maps.Infobox(addresspinLocation, addressinfoboxOptions);
addressSearchPin.push(addressInfobox);
show_addressSearchInfobox_in_URL=true;
}

function GeocodeCallback(result)
{
if(!(result.resourceSets[0].resources[0]==undefined))
{
//if the location is found by Bing
if (result && result.resourceSets && result.resourceSets.length > 0 && result.resourceSets[0].resources && result.resourceSets[0].resources.length > 0)
{
address_found=true;
//get the latitude/longitude of the address
address_pin_lat=result.resourceSets[0].resources[0].point.coordinates[0];
address_pin_lon=result.resourceSets[0].resources[0].point.coordinates[1];
addressSearchAddress = result.resourceSets[0].resources[0].name;
}
address_search_func();
setTimeout("add_visited_address()", 1);

}
else
alert("Please enter a valid address.");
}

kberry
07-24-2011, 02:07 PM
So after a while, I figured out that setTimeout will do the trick - albeit in a very hackish way. Here's the final code that will only add the address if it's not already added.



var Dom = {
get: function(el) {
if (typeof el === 'string') {
return document.getElementById(el);
} else {
return el;
}
},
add: function(el, dest) {
var el = this.get(el);
var dest = this.get(dest);
dest.appendChild(el);
},
remove: function(el) {
var el = this.get(el);
el.parentNode.removeChild(el);
}
};
var Event = {
add: function() {
if (window.addEventListener) {
return function(el, type, fn) {
Dom.get(el).addEventListener(type, fn, false);
};
} else if (window.attachEvent) {
return function(el, type, fn) {
var f = function() {
fn.call(Dom.get(el), window.event);
};
Dom.get(el).attachEvent('on' + type, f);
};
}
}()
};

Event.add(window, 'load', function() {
var i = 0;
Event.add('addressSearch', 'click', function() {
//This is a hack way of doing things...thanks asyncronous callbacks... /sarcasm
add_visited_address();
});
});

var visited_address_array = Array();
var address_check=0;
var MAX_ADDRESS_CHECKS=10;

function in_visited_address_array(new_entry)
{
for(var i=0; i<visited_address_array.length; i++)
{
if(new_entry == visited_address_array[i])
return true;
}
//otherwise...
return false;
}

function add_visited_address()
{
if(addressSearchAddress !=null)
{
var el = document.createElement('span');
var new_entry = addressSearchAddress + ' : [' + addressSearchRadius + ']';
el.innerHTML = '&nbsp;&nbsp;' + new_entry + '<br>';
if(!in_visited_address_array(new_entry))
{
visited_address_array.push(new_entry);
Dom.add(el, 'AddressesVisited');
Event.add(el, 'click', function(e) {Dom.remove(this);});
address_check=0;
}
else if(visited_address_array[visited_address_array.length-1] == new_entry && address_check<MAX_ADDRESS_CHECKS)
{
setTimeout("add_visited_address();", 100);
address_check++;
}
}
else
setTimeout("add_visited_address();", 50);
}

xelawho
07-24-2011, 02:15 PM
well I'm glad you got it working, albeit in a hackish manner. :thumbsup:

kberry
07-24-2011, 04:51 PM
Haha yes. Thanks for taking the time to help me with it. :)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum