【问题标题】:Javascript, how can I synchronously call function every second in the loop?Javascript,如何在循环中每秒同步调用函数?
【发布时间】:2020-08-02 20:31:49
【问题描述】:

我很难使用 async/await 使其在循环中同步工作。 我的小 showChart 所做的是从服务器请求 10 个项目并使用 plotly 在服务器上绘制它。 为了让它像每秒都来一样,我喜欢把一些睡眠时间最好精确到 1000 毫秒。然而,console.log 似乎每秒打印一次,但 drawChart 函数不是每秒调用一次,而是在最后一分钟显示所有内容。我怎样才能让它每秒画一次? 先谢谢了~~!!

/**
 * data comes with { status: '' , message:{ result : [{point:''}, {point:''} ...]}} in json format.  
**/
async function  showChart(url, nextPage ){
        let requestUrl  = url+nextPage;
        let resposne = await fetch(requestUrl);
        let data = await resposne.json();
        data = data.message.result;
        let points = await data.map(e=>e.point);
        console.log(fp1Deltas);
        const num =  fp1Deltas.map(  async delta =>{
           delay(1000);
           // await sleep (1000);
           drawChart(delta);
           console.log( delta);
         });
        console.log('done');       
    }

    const sleep = ms=>{
        return new Promise(resolve => setTimeout(resolve, ms));
    }

 const delay = ( ms)  => {
            var start = new Date().getTime();
            var end = start;
            while( end < start + ms ){
                end = new Date().getTime();
            }
    };

    const  drawChart = point =>{

        Plotly.extendTraces('chart1', {
            y: [
                 [point]
            ]
        }, [0]);
    }

    $(document).ready(function () {
        Plotly.plot('chart1', [{
            y: [],
            type: 'line'
        }]);
        showChart(requestLocation, page);
        // fetchData(requestLocation,page);

    }); // end of document ready

【问题讨论】:

  • 你基本上永远不需要像delay这样的函数。 (sleep 可以。)
  • await data.map(e=&gt;e.point); 中的 await 没有意义
  • 是的。 await 在这个特定示例中没有意义。我在考虑有很多数据需要处理的情况。所以需要一段时间才能解决。

标签: javascript loops asynchronous callback


【解决方案1】:

如果您想遍历fplDeltas 并调用drawChart 每个增量,间隔一秒,您可以这样做:

// So we skip the `sleep` the first time
let first = true;
for (const delta of fplDeltas) {
    // Sleep on all but the first
    if (first) {
        first = false;
    } else {
        await sleep(1000);
    }
    // Draw the chart
    drawChart(delta);
}

因为这是在 async 函数中,所以 await sleep(1000)(注意:不是 delay,你的基于承诺的sleep)让浏览器允许它进行任何绘图,等等

这是一个简单的例子,只是在 drawChart 中添加一个 DOM 元素:

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

async function example() {
    const fplDeltas = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let first = true;
    for (const delta of fplDeltas) {
        // Sleep on all but the first
        if (first) {
            first = false;
        } else {
            await sleep(1000);
        }
        // Draw the chart
        drawChart(delta);
    }
}

function drawChart(delta) {
    const div = document.createElement("div");
    div.textContent = delta;
    document.body.appendChild(div);
}

(async () => {
    try {
        await example();
        console.log("Done");
    } catch (e) {
        console.error("Error:", e);
    }
})();

【讨论】:

  • (Doh!如果您没有看到实时示例,请点击刷新——在添加实时示例之前,我遇到了一个愚蠢的逻辑错误。)
  • 谢谢~非常感谢~。有用 。我猜常规的 for 循环有效,但 map 无效。
  • @CharlieSiNB - map 不会对回调返回的承诺做任何事情(除了构建一个包含这些承诺的新数组),它只是继续通过数组进行下一次迭代。通常,仅在以下情况下将async 函数作为回调传递:A)如果回调返回一个 Promise,您知道调用回调的事物会理解它,或者 B)调用回调的事物会为您存储返回值并将它们提供给稍后再使用结果。
  • 因此,将async 函数与map 结合使用会很有用,但前提是您需要一组promise(无需等待它们中的任何一个解决)。例如,当您想要启动一堆将并行运行并等待它们全部完成的异步事物时,这很方便(await things.map(async (thing) =&gt; { /*...*/ });)。 map 几乎是唯一一个没有明确处理将 async 函数传递给的承诺的函数。
猜你喜欢
  • 2019-07-24
  • 2017-12-16
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
相关资源
最近更新 更多