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

d3.js、JavaScript中如何从Promise返回非pending状态的已决议值?

问题根本原因

所有被async关键字修饰的函数,JavaScript语言规范会强制将它的返回值包装为Promise对象,这是固定规则,和你函数内部返回什么值无关。你在函数内部await拿到的是解析后的值,但是返回的时候会被自动再包一层Promise,所以你直接调用async函数拿到的永远是Promise实例,不可能直接拿到原始值。


可行解决方案

以下方案均可以避免重复编写异步代码,符合你的使用需求:

方案1:全局变量缓存+初始化预加载

适合所有用到数据的逻辑都可以在数据加载完成后再执行的场景,后续使用完全不需要写异步代码:

// 提前定义全局缓存变量
let countryData = null;

async function init() {
  // 页面初始化阶段就加载数据,赋值给全局变量
  countryData = await generateCountryData();
  // 所有依赖该数据的业务逻辑,都在拿到数据后再调用
  runBusinessLogic();
}

// 后续任何普通同步函数里都可以直接使用
function runBusinessLogic() {
  // 直接读取全局变量,拿到的就是解析完成的数组
  console.log(countryData);
}

// 页面加载时启动初始化
window.onload = init;

方案2:缓存Promise实例,避免重复异步逻辑

如果没法保证业务逻辑的执行顺序,或者部分逻辑可能在数据加载完成前触发,可以直接缓存Promise实例,每次使用时await即可,只会发起一次请求,也不需要重复定义异步逻辑:

// 只调用一次生成数据的函数,缓存Promise实例
const cachedCountryDataPromise = generateCountryData();

// 任何需要用到数据的地方,直接await这个缓存的Promise即可
async function needDataFunction1() {
  const data = await cachedCountryDataPromise;
  // 处理逻辑
}

async function needDataFunction2() {
  const data = await cachedCountryDataPromise; // 不会重复请求csv,直接拿已解析的结果
  // 处理逻辑
}

注:await已经处于fulfilled状态的Promise没有额外开销,会直接返回解析后的值,不需要担心性能问题。

方案3:入口处一次性获取数据,传参给下游同步函数

只在最上层的入口函数里用一次async/await,拿到数据后作为参数传给所有下游的同步业务函数,下游函数完全不需要写异步逻辑:

// 所有业务函数都是普通同步函数,不需要async修饰
function processData(data) {
  // 数据处理逻辑
}
function renderD3Chart(data) {
  // d3渲染逻辑
}

// 仅在最上层入口处使用一次异步逻辑
async function mainEntry() {
  const countryData = await generateCountryData();
  // 把数据作为参数传给所有需要的同步函数
  processData(countryData);
  renderD3Chart(countryData);
}

mainEntry();

注意JavaScript的异步IO规则无法突破,不存在任何方法可以同步获取到异步请求(比如d3.csv的网络请求)的结果,上述方案都是在现有规则下减少重复异步代码的最优实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:36:03