要在 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_ 开头的密钥。将其设为环境变量:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here免费套餐每月含 5,000 次调用,支持以 31 种货币报价的黄金现货价格。无需信用卡。
安装 decimal.js
Node 18+ 内置原生 fetch,无需 HTTP 客户端。唯一依赖是 decimal.js,用于精确计算价格,避免 JavaScript Number 类型的精度误差。安装命令如下:
npm install decimal.js编写 goldprice 客户端
将代码保存为 goldprice.mjs。spot() 按交易符号在 Map 中缓存 60 秒,遇到 429 时按指数退避最多重试 3 次,并以 Decimal 返回价格。可选的买入价和卖出价仅限付费套餐,缺失时为 null。
// 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。
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 次。
// USD spot, defaultawait spot("XAU-USD-SPOT");await spot("XAU-INR-SPOT");await spot("XAU-EUR-SPOT");// Silver in USDawait spot("XAG-USD-SPOT");预期输出
{ "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 401 | API 密钥缺失或无效。运行 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 重试次数指标