教程代码

如何在 Node.js 中获取实时金价

在 Node.js 中调用 goldprice.dev API,使用原生 fetch、decimal.js、429 重试和有效期为 60 秒的缓存。

2026年7月5日 · 阅读时间:3 分钟

要在 Node.js 中获取实时金价,请使用原生 fetch 向 api.goldprice.dev/v1/spot/XAU-USD-SPOT 发送 GET 请求,并在 X-API-Key 请求头中传入 API 密钥,无需 HTTP 库。用 Map 缓存响应 60 秒,用 decimal.js 计算价格。免费套餐每月含 5,000 次调用,无需信用卡。已于 2026 年七月在 Node 22 LTS 上测试。

获取 goldprice.dev API 密钥

前往 goldprice.dev/onboarding 注册免费账户。验证邮箱后,控制台会显示以 ga_live_ 开头的密钥。将其设为环境变量:

Shell
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here

免费套餐每月含 5,000 次调用,支持以 31 种货币报价的黄金现货价格。无需信用卡。

安装 decimal.js

Node 18+ 内置原生 fetch,无需 HTTP 客户端。唯一依赖是 decimal.js,用于精确计算价格,避免 JavaScript Number 类型的精度误差。安装命令如下:

shell
npm install decimal.js

编写 goldprice 客户端

将代码保存为 goldprice.mjs。spot() 按交易符号在 Map 中缓存 60 秒,遇到 429 时按指数退避最多重试 3 次,并以 Decimal 返回价格。可选的买入价和卖出价仅限付费套餐,缺失时为 null。

goldprice.mjs
// node: goldprice.mjs// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTimport Decimal from "decimal.js";const API_BASE = "https://api.goldprice.dev";const API_KEY = process.env.GOLDPRICE_API_KEY;if (!API_KEY) {  throw new Error("GOLDPRICE_API_KEY not set");}const TTL_MS = 60_000;const cache = new Map();/** Fetch live spot price. Cached 60s per symbol, retries 3x on 429. */export async function spot(symbol = "XAU-USD-SPOT") {  const cached = cache.get(symbol);  if (cached && cached.expiresAt > Date.now()) {    return cached.data;  }  let lastErr;  for (let attempt = 0; attempt < 3; attempt++) {    const res = await fetch(`${API_BASE}/v1/spot/${symbol}`, {      headers: { "X-API-Key": API_KEY },      signal: AbortSignal.timeout(5000),    });    if (res.status === 429) {      lastErr = new Error("goldprice: 429 rate limited");      const backoffMs = 2 ** attempt * 1000; // 1s, 2s, 4s      await new Promise((resolve) => setTimeout(resolve, backoffMs));      continue;    }    if (!res.ok) {      throw new Error(`goldprice: unexpected status ${res.status}`);    }    const raw = await res.json();    const data = {      symbol: raw.symbol,      quoteCurrency: raw.quote_currency,      price: new Decimal(raw.price),      bid: raw.bid == null ? null : new Decimal(raw.bid),      ask: raw.ask == null ? null : new Decimal(raw.ask),      isStale: raw.is_stale,      computedAt: raw.computed_at,    };    cache.set(symbol, { data, expiresAt: Date.now() + TTL_MS });    return data;  }  throw lastErr;}

运行代码

导入模块并调用 spot()。首次调用会请求 API,60 秒内的后续调用直接返回缓存中的 Decimal,无需网络请求。缓存仅存在于进程内,重启后清空。需要跨进程共享时,可使用 Redis。

run.mjs
import { spot } from "./goldprice.mjs";const r = await spot("XAU-USD-SPOT");console.log(`${r.symbol}-${r.quoteCurrency}: ${r.price} (computed ${r.computedAt})`);// XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)

切换货币或金属

交易符号格式为 METAL-CURRENCY-SPOT。可向 spot() 传入使用任意一种受支持的 31 种现货报价货币的交易符号。每个符号在 Map 中独立缓存。多币种控制台每隔 60 秒轮询 5 个符号时,未命中缓存每分钟发出 5 次 API 调用,命中缓存时为 0 次。

goldprice.mjs · 多币种
// USD spot, defaultawait spot("XAU-USD-SPOT");await spot("XAU-INR-SPOT");await spot("XAU-EUR-SPOT");// Silver in USDawait spot("XAG-USD-SPOT");

预期输出

JSON
{  "symbol": "XAU",  "quote_currency": "USD",  "unit": "troy_ounce",  "contract_type": "spot",  "price": "4012.75",  "is_stale": false,  "computed_at": "2026-10-23T07:00:18.221118+00:00"}

标准输出显示一行内容:交易符号、报价货币、decimal.js Decimal 类型的价格,以及 ISO 8601 格式的 computedAt 时间戳。下游代码使用 spot() 返回的普通对象。

常见错误

代码现象解决方法
401首次调用出现 goldprice: unexpected status 401API 密钥缺失或无效。运行 echo $GOLDPRICE_API_KEY 确认变量已设置。如果为空,请从控制台复制密钥并重新导出。环境变量为空时,模块会在导入时抛出异常,让问题立即暴露。
429按退避间隔重试三次仍返回 429,随后 spot() 返回拒绝状态已达到每分钟调用上限。60 秒缓存可避免稳定轮询触及此限制。如果同时请求大量不同符号,请错开调用时间。持续高频使用可查看 /pricing 的付费套餐。
N/A价格看似正确,但反复计算后出现细微偏差JavaScript Number 使用 IEEE-754 浮点数:0.1 + 0.2 === 0.30000000000000004。金价保留 2 位小数,用 Number 累加数千个值会产生基点级误差。计算时始终使用 decimal.js 的 Decimal,仅在显示或序列化时调用 .toString() 或 .toNumber()。

进阶用法

  • 跨进程保存缓存:用 Redis 缓存替换 Map,让多个工作进程共享已缓存的价格
  • 为 /v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=... 添加 bars() 封装,将时间序列用于回测
  • 将客户端接入 Express 或 Fastify 路由,为非 Node 服务提供内部接口
  • 合并同一未缓存符号的并发请求,让突发调用只触发一次 fetch
  • 通过 Prometheus 提供缓存命中率、p50/p95 延迟和 429 重试次数指标

常见问题

价格多久更新一次

现货接口每隔 60 秒刷新一次,提供实时现货数据。免费套餐和免密钥价格延迟 15 分钟,付费套餐提供实时价格。上述缓存的有效期同为 60 秒,期间重复调用 spot() 会直接返回缓存中的 Decimal,无需网络请求。

自动刷新会超出免费额度吗

取决于调用方式。每分钟轮询一次 = 每天 1,440 次 = 每月约 43,000 次,远超每月 5,000 次的免费额度。请充分使用缓存,并按需调用。每小时轮询一次约为每月 720 次,在免费额度内。持续高频使用可查看 /pricing 的付费套餐。

可以商用吗

所有套餐都允许商用。付费套餐无需添加署名链接。使用免费套餐时,必须在价格附近放置清晰可见的 goldprice.dev 链接。

为什么使用 decimal.js 而不用 Number

JavaScript 的数值类型是 64 位浮点数,累加时会产生偏差:0.1 + 0.2 的结果是 0.30000000000000004。金价保留 2 位小数,用 Number 长期累加数千个值会产生基点级误差。decimal.js 支持精确计算。API 以字符串返回价格,让客户端可无损构造 Decimal。

需要 TypeScript 或构建步骤吗

不需要。示例使用普通 ES 模块(.mjs),Node 18+ 可原生运行,无需转译器。如果项目使用 TypeScript,同样的代码可直接放入 .ts 文件。fetch、AbortSignal.timeout 和 decimal.js 均自带类型定义。

支持哪些金属

支持黄金(XAU)、白银(XAG)和铜(HG)。所有套餐均不提供铂金和钯金。替换交易符号中的金属代码即可,例如 spot("XAG-USD-SPOT")。

免费套餐真的免费吗

是的,每月含 5,000 次调用,无需信用卡,也没有到期时间。前往 /onboarding 获取密钥。

可以让 Claude 帮我编写吗

可以。在已安装 goldprice.dev MCP 服务器的 Claude Desktop 中输入:为 goldprice.dev /v1/spot 接口编写 Node.js 客户端。使用原生 fetch、decimal.js、有效期为 60 秒的 Map 缓存,以及遇到 429 时的指数退避重试。从 GOLDPRICE_API_KEY 读取 API 密钥。MCP 服务器会向 Claude 提供最新结构定义,使生成的代码首次就能使用正确的字段名。

继续阅读

从免费 API 密钥开始

免费套餐每月提供 5,000 次请求。无需信用卡。

获取免费密钥