依序循环修改多个Highcharts

时间:2019-03-27 21:59:04

标签: javascript highcharts promise es6-promise

摘要

我目前在给定页面上有大约14个以上的股票图表的环境中工作(每个图表都有20,0000+个唯一数据点,还有更多)。我有某些全局“切换”,例如,影响显示的系列,图表选项或极限轴(在所有图表上)。鉴于一次只能显示一个图表给用户,我想将更新图表视为一个队列,在该队列中,我先更新一个图表,然后再更新另一个,依此类推。

我的目标:依次循环调用Highcharts.Chart.redraw()(即,一次对页面中的每个图表调用redraw,以便首先重绘我的图表列表中的第一个图表)。请注意,图表列表的顺序是动态创建的,已经处理完毕。

背景

到目前为止,我已经阅读了很多关于JavaScript Promise的信息,这些信息在过去用于链接Ajax调用。如以下链接所述:

我还在此处阅读了一些与循环中的Promises相关的一般问题:

代码/详细信息

我尝试了许多解决方案,并认为问题围绕使Highcharts重绘功能-或调用该功能的动作(如Chart.update(),Series.setVisible(),Axis.setExtremes())-返回承诺。

我已经上传了一个外壳here,它允许您触发一个事件,并且看到每个图表实际上都可以一次更新。


例如,如下所示:

$(Highcharts.charts).each(function(i, chart) {
    console.log(i);
    // decide what to do with the chart
    // update Series, Chart options, Axis extremes... etc.
    chart.redraw(); // call redraw at the end
})

将输出:

> 1, 2, 3, ..., n // pause, then charts would redraw()

可能很重要的一点是,尽管上面的内容似乎是响应式的,但在我的环境中,单击切换按钮和图表的重绘事件之间可能会有2-5秒的延迟。

我不知道要如何使循环等待每个图表完成其重绘,然后再进入列表中的下一个图表。

我们将不胜感激。

2 个答案:

答案 0 :(得分:2)

如果我理解您的意思,则可以通过将触发器中的代码包装到setTimeout(超时值为0)中,然后包装在新的Promise中来实现

使用async / await就像

$('#trigger').click(async (e) => {
    for (let chart of Highcharts.charts) {
        await new Promise(resolve => setTimeout(() => {
            chart.series.forEach(series => series.setVisible(undefined, false));
            chart.redraw();
            resolve();
        }, 0));
    }
});

答案 1 :(得分:1)

通用解决方案

通常,如果您要按顺序依次链接诺言,可以使用以下格式

function promiseChain(i) {
    return new Promise(resolve => {
        /* DO ASYNC STUFF */

        // Resolve with some result if the next item in the chain needs it
        return resolve("OK");
    });
}

let p = Promise.resolve(null);

for (let i = 0; i < 5; i++) {
    p = p.then(prevResult => {
        if (prevResult) {
            // Do stuff with prevResult if needed
        }

        // Chain next item
        return promiseChain(i);
    });
}

带有日志的示例

这将记录数字0-4,一次记录一次,每次之间等待一秒钟。

function promiseChain(i) {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(i);
            return resolve("OK");
        }, 1000)
    });
}

let p = Promise.resolve(null);

for (let i = 0; i < 5; i++) {
    p = p.then(prevResult => {
        if (prevResult) {
            // Do stuff with prevResult if needed
        }

        return promiseChain(i);
    });
}