Reputation: 6933
Always thought that javascript was not asynchronous unless Ajax or something else was used. I'm not using Ajax calls or anything, but my JS function doesnt seem to wait for a return value:
I have three lines of code as follows:
var areas = prepareComparer();
console.log('Areas');
console.log(areas);
I need to create an overlay div suing the following function:
function prepareComparer() {
var comparorSelection = d3.select('body').append('div').attr('id', 'comparor').attr('style', 'line-height: 100px;position: fixed;top: 5%; left:5%;background-color: white;border-radius: 5px;text-align: center;z-index: 2;border-style:solid;border-width:1px;box-shadow: 10px 10px 5px #888888')
.transition().duration(500).style('height', '800px').style('width', $(window).width() * .9 + 'px').style('opacity', '1').each('end', function () {
//Waiting for end of transition to append the comparees: Otherwise, causes size adjustment problems since comparee sizes depend on the FULL height.
d3.select('#comparor').append('div').attr('id', 'comparee1').attr('style', 'position:absolute;top:0px;left:0px;width:' + $('#comparor').width() * .45 + 'px;height:' + $('#comparor').height() + 'px')
.append('svg');
d3.select('#comparor').append('div').attr('id', 'comparee2').attr('style', 'position:absolute;top:0px;left:' + $('#comparor').width() * .5 + 'px;width:' + $('#comparor').width() * .45 + 'px;height:' + $('#comparor').height() + 'px')
.append('svg');
d3.select('#comparor').append('div').attr('id', 'destroyComparor').text('Click Here To Go Back').on('click', function () {
d3.select('#comparor').transition().duration(500).style('width', '0px').style('height', '0px').style('opacity', '0').remove();
});
});
setTimeout(function () { console.log("Hello"); return ['#comparor #comparee1', '#comparor #comparee2'] }, 5000);
}
Now, for this, my log shows up as:
Areas
undefined
Hello
Ignore the d3 code, as commenting or uncommenting it doesnt seem to make much of a difference. Just to be sure, Ive introduced a timeout of 5 seconds. So, after 5 seconds I get the message Hello, meaning that return also might be happening after that. Im getting the undefined message almost immediately.
I'm not really sure why this is happening and have been trying to decode this for ages. Can anyone help?
Edit
Wanted to return a data on completion of new div creation(#comparee1 and #comparee2) in the code. But, a delay was introduced due to the d3 transitions which are asynchronous. And since the new divs were created only after transition completion(there were size dependencies), the newly created divs could not be selected by my main function immediately.
Resolved this problem with using JavaScript Promises:
function prepareComparer() {
promise = new Promise(function (resolve, reject) {
var comparorSelection = d3.select('body').append('div').attr('id', 'comparor').attr('style', 'line-height: 100px;position: fixed;top: 5%; left:5%;background-color: white;border-radius: 5px;text-align: center;z-index: 2;border-style:solid;border-width:1px;box-shadow: 10px 10px 5px #888888')
.transition().duration(500).style('height', '800px').style('width', $(window).width() * .9 + 'px').style('opacity', '1').each('end', function () {
//Waiting for end of transition to append the comparees: Otherwise, causes size adjustment problems since comparee sizes depend on the FULL height.
d3.select('#comparor').append('div').attr('id', 'comparee1').attr('style', 'position:absolute;top:0px;left:0px;width:' + $('#comparor').width() * .45 + 'px;height:' + $('#comparor').height() + 'px')
.append('svg');
d3.select('#comparor').append('div').attr('id', 'comparee2').attr('style', 'position:absolute;top:0px;left:' + $('#comparor').width() * .5 + 'px;width:' + $('#comparor').width() * .45 + 'px;height:' + $('#comparor').height() + 'px')
.append('svg');
d3.select('#comparor').append('div').attr('id', 'destroyComparor').text('Click Here To Go Back').on('click', function () {
d3.select('#comparor').transition().duration(500).style('width', '0px').style('height', '0px').style('opacity', '0').remove();
});
resolve(['#comparor #comparee1', '#comparor #comparee1']);
});
});
}
and the function using the data would be called as:
promise.then(function (response) {
window[func](response[0], res, 'label', 'value');
});
Just wanted to share the solution.
Upvotes: 0
Views: 111
Reputation: 11
put a return before setTimeout cause function will wait set timout finished
look like this
return setTimeout(function () { console.log("Hello"); return ['#comparor #comparee1', '#comparor #comparee2'] }, 5000);
sorry doesn't work but as you have no return areas will always be undifined.
for the async problem traceur.js introduce await keyword that will probably be usefull for you
Upvotes: -2
Reputation: 2086
Your function prepareComparer()
has no return. In JavaScript functions without return return undefined.
The return inside the setTimeout()
is irrelevant for prepareComparer()
.
And here you found an other aspect of asynchrous programming in JavaScript besides Ajax.
Upvotes: 3