在使用Node v14.14.0中的顶级await功能时,出现“SyntaxError:await仅在异步函数中有效”的错误。

4

我正在尝试使用在Node v14.8中添加的新的顶层等待功能。

请查看此处此处 获取更多信息。我没有在这里找到一个关于使用这个新功能时出现问题的问题,但我希望这不是重复的。最接近的是@DanStarns在这个问题上的答案,但我也尝试过他的解决方案(而且他的答案是在14.8发布之前的)。

  • 我知道过去IIFE一直是解决方法之一,但这个问题涉及到新的顶层等待功能,以及为什么尽管已经随着Node 14.8的发布而释放了,却会抛出错误

我正在将我的Axios实例从控制器中提取到一个独立的服务中。在那个服务文件中,我试图使用存储的Spotify API授权标头创建一个Axios实例并导出它。由于这是在我的控制器中导入的(通过将其传递给构造函数,然后导出new SpotifyApiController(SpotifyApiService)),并且导入是同步的,因此我正在尝试使用新的顶层等待功能,在启动/导入时完全实例化它,但是出现以下错误:

[nodemon] starting `babel-node bin/www.js --harmony-top-level-await --experimental-repl-await`
E:\projects\harmonic-mixing-companion\server\services\SpotifyApiService.mjs:117
var SpotifyApiService = await createApiService();
                        ^^^^^

SyntaxError: await is only valid in async function
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Module._compile (E:\projects\harmonic-mixing-companion\server\node_modules\pirates\lib\index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.newLoader [as .mjs] (E:\projects\harmonic-mixing-companion\server\node_modules\pirates\lib\index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (E:\projects\harmonic-mixing-companion\server\controllers\/SpotifyApiController.js:1:1)

从这个错误来看,babel-node正确地将我的代码转译了,因为const SpotifyApiService = ...变成了var SpotifyApiService = ...。我还在我的babel.config.json中添加了"@babel/plugin-syntax-top-level-await"

服务的文件扩展名是.mjs。我也尝试在服务器的package.json中设置"type": "module",但没有效果。如果我错了,请纠正我,但对我而言,将整个后端服务器设置为模块化单元似乎不太正确(相对于可重用的SpotifyApiService)。

在我的主入口文件顶部使用console.log(process.version);双重检查了我的node版本,输出了预期的14.14.0版本。


SpotifyApiController.js片段:

import SpotifyApiService from '../services/SpotifyApiService.mjs';
import handleHttpError from '../handlers/handleHttpError';

class SpotifyApiController {
  constructor(spotifyApiService) {
    this.spotifyApi = spotifyApiService;
  }
  ...
}

SpotifyApiService.mjs 代码片段:

...
const createApiService = async () => {
  const accessToken = await authorizeApp();

  console.log(accessToken);

  const authHeader = { Authorization: `Bearer ${accessToken}` };

  const axiosInstance = axios.create({
    baseURL: 'https://api.spotify.com/v1',
    headers: authHeader,
  });

  createAuthRefreshInterceptor(axiosInstance, authorizeApp);

  return axiosInstance;
};

const SpotifyApiService = await createApiService();

export default SpotifyApiService;

package.json 的依赖项:

  "devDependencies": {
    "@babel/cli": "~7.12.1",
    "@babel/core": "~7.12.1",
    "@babel/eslint-parser": "~7.12.1",
    "@babel/node": "~7.12.1",
    "@babel/plugin-proposal-class-properties": "~7.12.1",
    "@babel/plugin-syntax-top-level-await": "~7.12.1",
    "@babel/plugin-transform-arrow-functions": "~7.12.1",
    "@babel/plugin-transform-runtime": "~7.12.1",
    "@babel/preset-env": "~7.12.1",
    "@babel/preset-react": "~7.12.1",
    "babel-loader": "~8.1.0",
    "nodemon": "~2.0.5"
  },
  "dependencies": {
    "axios": "~0.20.0",
    "axios-auth-refresh": "~3.0.0",
    "cookie-parser": "~1.4.5",
    "cors": "~2.8.5",
    "debug": "~4.2.0",
    "dotenv": "~8.2.0",
    "express": "~4.17.1",
    "querystring": "~0.2.0"
  }

服务器是通过下面的npm脚本启动的:"dev-server": "nodemon --exec babel-node bin/www.js --ignore dist/"

3个回答

7
你可以将其包装在异步函数中:
var SpotifyApiService = (async()=> await createApiService())();

在你使用完成后,可以使用than、catch


我知道IIFE曾经是过去的一种解决方法(个人不太喜欢IIFE语法,但我岔开了话题),但这个问题涉及到新的顶级等待功能,为什么它会抛出错误,尽管已经在Node 14.8中发布(请参见有关该功能的nodejs的关闭PR 此处)。 - Azanadra
我看到你添加了 plugin-syntax-top-level-await。但是,也许你尝试过 --experimental-top-level-await 标志了吗? - Odinn

3
根据文档,Babel仅启用此功能的“语法”,

仅限语法

该插件仅启用此功能的解析。 Babel不支持转换顶层等待,但您可以使用Rollup的experimentalTopLevelAwait或webpack@5的experiments.topLevelAwait选项。

这意味着当编译您的代码时,Babel不会抱怨,但它实际上不会执行将var SpotifyApiService = await createApiService(); 这一行转换为有效的ES5所需的步骤。
因此,任何执行您的代码的程序(浏览器、node)都会抱怨,因为它们不知道如何处理这个特性。

0
问题在于顶级等待仅支持 ES 模块。换句话说,您必须将 "type": "module" 添加到您的 package.json 或将您的 .js 文件重命名为 .mjs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接