异步等待 in() 函数 setInterval()。如何让它变得聪明?

Posted

技术标签:

【中文标题】异步等待 in() 函数 setInterval()。如何让它变得聪明?【英文标题】:asynch await ping() function setInterval(). How to make it smart? 【发布时间】:2022-01-23 10:20:14 【问题描述】:

以下代码 ping 我的 nginx 服务器上的 NGINX 位置块,为您提供健康检查状态。

const ping = async () => 
  const url = `http://10.10.1.100/status`;
  const postData = 
    method: 'POST', // *GET, POST, PATCH, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    headers: 
      'Content-Type': 'text/plain; charset=ASCII'
    ,
    body: 'PING'
  
    try 
      let factor = 1;
      let timeout = 3000; // ms
      let start = (new Date()).getTime();
      const request = await fetch(url, postData);
      let delta = new Date().getTime() - start;
      delta *= (factor || 1);
      if(delta > timeout) throw new Error(`PONG > $timeoutms. Server down?`);
      if(!request.ok) throw new Error(`$request.status $request.statusText`);
      const response = await request.text();
      if(!response) throw new Error(`$response`);
      document.getElementById('serverPongSpeed').innerText = `$delta.toFixed(0)ms`;
      // Do Something...
      console.log(`%c$delta.toFixed(0)ms $response`, "color: #c6ff00"); // Lime A400
     catch (error) 
        console.log(error);
    

NGINX 位置块:

location = /status 
  access_log off;
  default_type text/plain;
  add_header "Access-Control-Allow-Methods" "POST";
  add_header "Content-Type" "text/plain";
  return 200 "PONG";

现在我是这样运行的:

setInterval(ping, 3000); // Every 3 seconds

问题是,在测试期间,当我关闭 NGINX 以查看 PING 不会中断时会发生什么。它只是不断发送 POST 请求。

也许这是我没有发现的错误?或者可能没有错误,因为 fetch 有更大的超时?也许将获取超时设置为 3 秒会触发一些东西让我抓到..

【问题讨论】:

也许有些东西会缓存您的请求。在您的 Url 请求中添加一些随机字符串结尾。 const url = http://10.10.1.100/status?v=+(new Date().valueOf()); 当你说它“不会中断”时,你的意思是它永远不会捕获 catch 块中的错误吗? 正确。我想在获取失败时至少显示0ms,因为我故意关闭了 NGINX。但似乎“获取”只是排队,直到我打开 NGINX。在这种情况下,他们从未成功完成。 关机后试试clear interval 【参考方案1】:

你可以像这样使用 ClearInterval() 方法:

  var interval = setInterval(ping, 3000);
  if(timeoutCounter > 3)
      clearInterval(interval)

您需要更多代码来计算超时/错误。 类似于断路器模式的东西

【讨论】:

我需要它来保持滴答作响。我想要的是它在 NGINX 关闭时简单地显示0ms。就像0ms 占位符。 哦!也许不是在!request.ok 时抛出错误,我应该输出0ms!试试看…… @suchislife 确切地说,你需要把你的逻辑放在 if 语句中而不是抛出异常【参考方案2】:

以下是所需工作解决方案的修订完整示例。

javascript asynch await ping 函数:

    Ping 函数设置为向 NGINX /status 位置块发送请求。 Ping 功能设置为超时 300 毫秒以指示可能的服务器 下来。 Ping 功能设置为使用预设指示增加的网络延迟 阈值。 Ping 功能设置为捕获网络级别错误和任何其他未知数 错误。 Ping 函数将输出返回到控制台。

...

window.onload = () => 

  let precision = 2; // decimals
  let pageLoadSpeed = ((window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart) / 1000).toFixed(precision);
  document.getElementById('pageLoadSpeed').innerText = `$pageLoadSpeeds`;
  console.log(`%cPage loaded in $pageLoadSpeed seconds.`, "color: #c6ff00"); // Lime A400

  let polling = null;

  // Network latency thresholds
  const settings = 
    pingInterval: 5000, // ms
    latency: 
      factor: 1.0, // Adjust latency to a percentage of its total
      high: 99, // ms
      moderate: 66, // ms
      low: 33, // ms
    ,
    timeout: 300, // ms
    consoleLogLimit: 10,
    consoleLogCount: 0,
  ;

  const ping = async() => 

    const url = `http://10.10.1.100/status`;

    const postData = 
      method: 'POST', // *GET, POST, PATCH, DELETE, etc.
      mode: 'cors', // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
      headers: 
        'Content-Type': 'text/plain; charset=ASCII'
      ,
      body: 'PING'
    

    try 

      const startWatch = (new Date()).getTime();

      const request = await fetch(url, postData);

      const stopWatch = (new Date().getTime() - startWatch) * (settings.latency.factor || 1);

      if (!request.ok) throw new Error(`$request.status $request.statusText`);

      const response = await request.text();

      if (!response) throw new Error(`$response`);

      if (stopWatch >= settings.timeout) 
        console.log(`%cPONG > $settings.timeoutms. Server down?`, "color: #d500f9"); // purple A400
       else if (stopWatch >= settings.latency.high) 
        console.log(`%c$response: $stopWatchms High Latency`, "color: #ff1744"); // red A400
       else if (stopWatch >= settings.latency.moderate) 
        console.log(`%c$response: $stopWatchms Moderate Latency`, "color: #ffc400"); // amber A400
       else if (stopWatch <= settings.latency.low) 
        console.log(`%c$response: $stopWatchms Low Latency`, "color: #00e676"); // green A400
      

      settings.consoleLogCount++;

      // Prevents browser from getting sluggish     
      if (settings.consoleLogCount == settings.consoleLogLimit + 1) 
        // Reset count
        settings.consoleLogCount = 0;
        // Clear console
        console.clear();
      

     catch (error) 

      // Catch network level error
      if (error instanceof TypeError && error.message == 'NetworkError when attempting to fetch resource.') 

        // Clear console
        // console.clear();

        console.error(`NGINX offline or Network cable unplugged?`);

        // Reset count
        settings.consoleLogCount = 0;

        // Stop polling
        clearInterval(polling);

       else 
        // Catch any other error
        console.error(error);
      

    

  

  polling = setInterval(ping, settings.pingInterval);


...

NGINX 服务器 /status 位置块:

    端点设置为仅接受 /location 端点上的 POST 请求。 端点访问日志设置为禁用,因为我们真的不需要 记录这个。 端点设置为响应,内容类型设置为 text/plain。 端点设置为接受来自任何来源的 POST 请求。 端点设置为返回 text/plain 的 Content-Type 和文本 成功时“PONG”响应。

...

location = /status 

  access_log off;

  default_type text/plain;

  limit_except POST 

    deny all;

  

  add_header Access-Control-Allow-Origin "*" always;
  add_header Access-Control-Allow-Methods "POST, OPTIONS" always;
  add_header Content-Type "text/plain" always;

  return 200 "PONG";


【讨论】:

以上是关于异步等待 in() 函数 setInterval()。如何让它变得聪明?的主要内容,如果未能解决你的问题,请参考以下文章

Js同步异步机制

同步和异步

setIntervalsetTimeoutrequestAnimationFrame

setInterval()解决异步加载,参数传递问题

使用 setInterval() 的无限异步循环 [重复]

等待异步任务完成后再继续?