Javascript不等待返回值

时间:2014-04-04 10:11:05

标签: javascript jquery ajax d3.js

除非使用Ajax或其他东西,否则一直认为javascript不是异步的。我没有使用Ajax调用或任何东西,但我的JS函数似乎不等待返回值:

我有三行代码如下:

var areas = prepareComparer();
console.log('Areas');
console.log(areas);

我需要使用以下函数创建一个overlay div:

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);
}

现在,为此,我的日志显示为:

Areas 
undefined 
Hello 

忽略d3代码,因为评论或取消注释它似乎没有太大的区别。只是为了确定,我已经引入了5秒的超时。所以,在5秒后我得到消息Hello,这意味着之后也可能发生返回。我几乎立即得到了未定义的消息。

我不确定为什么会发生这种情况,并且一直试图解码这个问题。有人可以帮忙吗?

修改

想要在代码中完成新div创建(#compreeree1和#compreree2)时返回数据。但是,由于d3转换是异步的,因此引入了延迟。并且由于新的div仅在转换完成后创建(存在大小依赖性),因此我的main函数无法立即选择新创建的div。

使用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']);
        });
    });
}

,使用数据的函数将被称为:

promise.then(function (response) {
     window[func](response[0], res, 'label', 'value');
});

只是想分享解决方案。

2 个答案:

答案 0 :(得分:3)

您的函数prepareComparer()无法返回。在没有返回的JavaScript函数中返回undefined。

setTimeout()内的回复与prepareComparer()无关。

除了Ajax,你在这里找到了JavaScript中异步编程的另一个方面。

答案 1 :(得分:-2)

在setTimeout导致函数等待设置时间结束之前放回一个

看起来像这样

return setTimeout(function () { console.log("Hello"); return ['#comparor #comparee1', '#comparor #comparee2'] }, 5000);

抱歉没有工作,但由于你没有返回区域,所以一直都是无人问津的。

对于异步问题,traceur.js引入了一个可能对你有用的await关键字