【问题标题】:'SyntaxError: await is only valid in async function' when using top level await feature in Node v14.14.0在 Node v14.14.0 中使用顶级等待功能时,“语法错误:等待仅在异步函数中有效”
【发布时间】:2021-02-03 00:04:53
【问题描述】:

我正在尝试使用 Node v14.8 中添加的新顶级等待。 有关更多信息,请参阅 herehere。我在这里没有找到有关使用此新功能的问题的问题,但我希望这不是重复的。最接近的是@DanStarns answer on this question,但我也尝试过他的解决方案(他的答案是在 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)

从错误来看,自从const SpotifyApiService = ... 变为var SpotifyApiService = ... 后,babel-node 似乎正在正确地转换我的代码。我还添加了"@babel/plugin-syntax-top-level-await" 到我的babel.config.json

服务的文件扩展名是.mjs。我也尝试在服务器的 package.json 中设置 "type": "module" ,但这也没有结果。如果我错了,请纠正我,但将我的整个后端服务器设置为一个模块对我来说也不合适,因为它对我来说听起来不像一个模块化单元(相对于可重复使用的 SpotifyApiService)。

使用主条目文件顶部的console.log(process.version); 仔细检查了我的节点版本,并打印了预期的 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/"

【问题讨论】:

    标签: javascript node.js express asynchronous async-await


    【解决方案1】:

    您可以将其包装在异步函数中:

    var SpotifyApiService = (async()=> await createApiService())();
    

    可以使用之后,catch

    【讨论】:

    • 我知道 IIFE 过去一直是首选解决方法之一(我个人不喜欢 IIFE 语法,但我离题了)但这个问题是关于新的顶级等待功能以及为什么尽管已与 Node 14.8 一起发布但它仍会引发错误(有关功能here,请参阅 nodejs 的已关闭 PR)
    • 我看到你添加了 plugin-syntax-top-level-await。但是 mb 你试过 --experimental-top-level-await 标志吗?
    【解决方案2】:

    正如documentation 所指出的,babel 只启用此功能的“语法”,

    仅语法

    此插件仅启用对此功能的解析。 巴别塔没有 支持转换顶层 await,但可以使用 Rollup 的 experimentalTopLevelAwait 或 webpack@5 的 Experiments.topLevelAwait 选项。

    这只是意味着 babel 在编译你的代码时不会抱怨,但它实际上并没有实现将诸如 var SpotifyApiService = await createApiService(); 之类的行主动转换为有效 ES5 的步骤。

    所以任何执行你的代码(浏览器、节点)的东西都会抱怨,因为他们不知道如何处理这个功能。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-23
        相关资源
        最近更新 更多