为什么使用setTimeout可以显示图表

时间:2019-01-21 09:32:30

标签: javascript typescript

我有一个单页应用程序。

在代码中,我获取数据,然后将其显示在图表中。

但是,存在计时问题:图表实例化之前就已获取数据。因此,图表最终没有显示任何内容。

我发现的解决方法是使用setTimeout()。但是奇怪的是,我只将间隔设置为1毫秒,然后图表可以正确显示。

我猜测真正发生的是通过使用setTimeout(),当前线程正在完成当前任务,然后返回到刷新功能并执行。那是对的吗?

我还有其他方法可以这样做,因为setTimeout()似乎有点黑,当然,我们也不想这么做。

这是获取数据的代码。

async getItemStatusSummary(parentId:number) {
    this.logger.info("getItemStatusSummary()");
    this.itemStatusInfos = await this.statInfoService.getItemStatusInfoByFolderId(parentId, 'ALL');
    this.refreshItemStatusSummaryChart();
}

这是刷新:

refreshItemStatusSummaryChart() {

    this.logger.info('RefreshingItemStatusSummaryChart()');
    const chart = $("#itemStatusSummaryChart").data("ejChart");
    if (chart) {
        chart.model.series[0].dataSource = this.itemStatusInfos;
        chart.animate(null);
    }
    else {
        this.logger.info('Chart is null');
        window.setTimeout(() => {
            this.refreshItemStatusSummaryChart();
        }, 1);
    }
}

3 个答案:

答案 0 :(得分:1)

从事物的Angular 1.x方面来看,这已成为一种公认的方式/技巧,它可以使彼此不同步的事物正常工作。

在angular中,仅强制执行另一个摘要循环,因此添加到示波器中的东西将显示出来。使用没有时间的setTimeout可以正常工作,而更多的是将其显示在执行堆栈的下方,而不是以任何方式实际延迟它。

我希望这会有所帮助,这是一件奇怪的事情,但是经过多年编写有角度的1.x应用程序后,我才习惯于这种奇怪的asycn行为来解决问题。

答案 1 :(得分:1)

您需要了解setTimeout在幕后所做的事情。

  

Philip Roberts对此有很好的论述,我对此高度评价   建议您听,我会在这里尽快解释。

JavaScript是一个单线程引擎,这意味着一次执行一个动作,这种行为称为 stack ,这意味着所有任务将按顺序执行。 setTimeout实际在做什么,就是将您的函数传递给它,并将其移到任务队列中,该队列正等待堆栈清除所有任务。然后,事件循环将从任务队列中获取您的功能,然后再次将其传递给堆栈

这意味着调用setTimeout将在堆栈的末尾执行传递的函数,而不管您定义等待的时间如何,以及为什么它使用值0

对于您来说,一个很棒的解决方案是使用 Zone.js ,而不是使用setTimeout。 在本答案中,我将不作介绍,而应对此问题进行检查article

答案 2 :(得分:0)

这不是您应该使用setTimeout的方式。您需要先返回承诺,然后执行 第二步。

async getItemStatusSummary(parentId:number) {

    this.logger.info("getItemStatusSummary()");

    this.statInfoService.getItemStatusInfoByFolderId(parentId, 'ALL')
                        .then ( response => {
                                this.itemStatusInfos = response;
                                this.refreshItemStatusSummaryChart();
                               });

}

关于您的第二项操作/方法,请删除setTimeout

refreshItemStatusSummaryChart() {

    this.logger.info('RefreshingItemStatusSummaryChart()');
    const chart = $("#itemStatusSummaryChart").data("ejChart");
    if (chart) {
        chart.model.series[0].dataSource = this.itemStatusInfos;
        chart.animate(null);
    }
    else {
        this.logger.info('Chart is null');
        this.refreshItemStatusSummaryChart();
    }
}