You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求实时获取外部JSON数据方案:替代定时轮询实现通知应用

Real-Time External JSON Data Fetching for Notification Apps

Hey there! Let's tackle this real-time JSON data fetching problem you're facing—those fixed-interval timeouts can be such a pain for a notification app, right? Either you're hitting the API too often (wasting resources) or missing updates because the interval's too long. Here are some practical, actionable solutions to try:

1. Server-Sent Events (SSE) – Simple One-Way Push

If you only need to receive updates (not send data back to the external source), SSE is way simpler than WebSockets. The catch? You'll need a small middleman server (since most external JSON APIs don't support SSE natively) that polls the external JSON, checks for changes, and pushes updates to your frontend via SSE.

Frontend Example (Browser JS):

const eventSource = new EventSource('/api/json-updates');

eventSource.onmessage = (event) => {
  const updatedData = JSON.parse(event.data);
  // Trigger your notification logic here
  showNotification(updatedData);
};

eventSource.onerror = (error) => {
  console.error('SSE connection error:', error);
  eventSource.close();
  // Optionally retry connection after a delay
};

Node.js Middleman Server Example:

const express = require('express');
const app = express();
const fetch = require('node-fetch');

let lastData = null;

// Endpoint for SSE
app.get('/api/json-updates', (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  // Initial check
  checkForUpdates(res);

  // Poll external JSON every 30 seconds (adjust as needed)
  const interval = setInterval(() => checkForUpdates(res), 30000);

  req.on('close', () => {
    clearInterval(interval);
    res.end();
  });
});

async function checkForUpdates(res) {
  try {
    const response = await fetch('https://external-api.com/data.json');
    const currentData = await response.json();

    if (JSON.stringify(currentData) !== JSON.stringify(lastData)) {
      lastData = currentData;
      // Send update to client
      res.write(`data: ${JSON.stringify(currentData)}\n\n`);
    }
  } catch (err) {
    console.error('Error fetching external JSON:', err);
  }
}

app.listen(3000, () => console.log('SSE server running on port 3000'));

2. Smart Polling with Dynamic Intervals

If you can't set up a middleman server, optimize your existing polling to avoid fixed intervals. Adjust the delay based on whether the data changed:

  • If data updates frequently, use a shorter interval
  • If no changes for a while, gradually increase the interval (to reduce API calls)

Example Code:

let pollInterval = 10000; // Start with 10 seconds
let lastData = null;

function pollForUpdates() {
  fetch('https://external-api.com/data.json')
    .then(res => res.json())
    .then(currentData => {
      if (JSON.stringify(currentData) !== JSON.stringify(lastData)) {
        lastData = currentData;
        showNotification(currentData);
        pollInterval = 10000; // Reset to short interval after update
      } else {
        // Increase interval by 5 seconds, cap at 60 seconds
        pollInterval = Math.min(pollInterval + 5000, 60000);
      }
      setTimeout(pollForUpdates, pollInterval);
    })
    .catch(err => {
      console.error('Polling error:', err);
      setTimeout(pollForUpdates, pollInterval); // Retry even on error
    });
}

// Start polling
pollForUpdates();

3. WebSockets with Middleman (For Two-Way or Low-Latency Needs)

You mentioned trying WebSockets without luck—chances are the external JSON API doesn't support WebSocket connections directly. The fix is to build a Node.js middleman that:

  1. Polls the external JSON API
  2. Detects changes
  3. Pushes updates to connected frontend clients via WebSockets

Node.js WebSocket Server Example (using ws library):

const WebSocket = require('ws');
const fetch = require('node-fetch');

const wss = new WebSocket.Server({ port: 8080 });
let lastData = null;

// Poll external JSON every 20 seconds
setInterval(async () => {
  try {
    const response = await fetch('https://external-api.com/data.json');
    const currentData = await response.json();

    if (JSON.stringify(currentData) !== JSON.stringify(lastData)) {
      lastData = currentData;
      // Send update to all connected clients
      wss.clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
          client.send(JSON.stringify(currentData));
        }
      });
    }
  } catch (err) {
    console.error('Error fetching external JSON:', err);
  }
}, 20000);

// Handle new client connections
wss.on('connection', (ws) => {
  console.log('New client connected');
  // Send initial data to new clients
  if (lastData) {
    ws.send(JSON.stringify(lastData));
  }

  ws.on('close', () => {
    console.log('Client disconnected');
  });
});

Frontend WebSocket Client:

const socket = new WebSocket('ws://localhost:8080');

socket.onopen = () => {
  console.log('WebSocket connection established');
};

socket.onmessage = (event) => {
  const updatedData = JSON.parse(event.data);
  showNotification(updatedData);
};

socket.onerror = (error) => {
  console.error('WebSocket error:', error);
};

socket.onclose = () => {
  console.log('WebSocket connection closed');
  // Optionally reconnect after a delay
  setTimeout(() => window.location.reload(), 5000);
};

Pro Tips to Optimize

  • Use HTTP Headers: Check the ETag or Last-Modified headers from the external API to avoid downloading the entire JSON every time. Only fetch the full data if the ETag has changed.
  • CORS Handling: If the external API doesn't allow cross-origin requests, your middleman server will handle this by proxying the request.
  • Rate Limiting: Make sure your polling interval respects the external API's rate limits to avoid getting blocked.

内容的提问来源于stack exchange,提问作者Dion Grendelman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:08:11