You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在异步函数参数默认值中使用await报错,属语言限制还是操作疏漏?

这是JavaScript的语言限制,不是你的操作疏漏哦!

嘿,首先明确告诉你:这个错误是JavaScript语言本身的设计限制,和你的操作没关系~

为啥会报错?

你之前用同步函数作为默认参数的写法没问题,因为同步函数可以在参数列表里立即执行。但异步场景不一样:

  • 哪怕你的外层函数加了async关键字,参数列表的执行上下文并不属于async函数的异步作用域
  • JavaScript规范明确规定:await只能出现在async标记的函数体内部,或者ES模块的顶层代码里——而参数列表既不属于函数体,也不是模块顶层,所以在这里用await会直接报错。

举个你可能尝试过的错误写法例子:

// 模拟耗时的数据库调用
const fetchDefaultData = async () => {
  return new Promise(resolve => setTimeout(() => resolve('默认数据'), 1000));
};

// 这样写会直接报错:'await' is not a valid identifier in this context
const myAsyncFunc = async ({ id }, data = await fetchDefaultData()) => {
  console.log(id, data);
};

靠谱的解决方案

既然参数列表里不能用await,我们换个思路在函数体内部处理默认值:

方案1:函数体内判断并赋值(最直观)

先给参数设一个占位默认值(比如undefined),然后在函数体里检查参数是否传入,没传入就异步获取默认值:

const fetchDefaultData = async () => {
  return new Promise(resolve => setTimeout(() => resolve('默认数据'), 1000));
};

const myAsyncFunc = async ({ id }, data) => {
  // 用空值合并运算符判断,如果data未传入则异步获取默认值
  data ??= await fetchDefaultData();
  console.log(id, data);
};

// 调用测试
myAsyncFunc({ id: 123 }); // 1秒后输出:123 默认数据
myAsyncFunc({ id: 123 }, '自定义数据'); // 立即输出:123 自定义数据

方案2:用同步函数返回Promise(特殊场景可选)

如果想在参数列表里定义逻辑,可以写一个同步函数返回Promise,但还是要在函数体里await这个结果:

const fetchDefaultData = async () => {
  return new Promise(resolve => setTimeout(() => resolve('默认数据'), 1000));
};

// 参数默认值是一个同步函数,返回Promise
const myAsyncFunc = async ({ id }, dataPromise = (() => fetchDefaultData())()) => {
  // 在函数体内await这个Promise
  const data = data ?? await dataPromise;
  console.log(id, data);
};

不过这个方案不如第一种直观,除非有特殊场景需求,否则更推荐方案1。

补充说明

JavaScript的参数默认值是在函数调用时同步计算的,这意味着哪怕你写了异步逻辑在参数默认值里,它也会同步触发,但你没法在参数列表里等待它完成——所以必须把等待的逻辑放到async函数的体内部,这是语言规范的要求哦。

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

火山引擎 最新活动