NodeJS中Await语法错误排查:async函数内为何仍报错?
我遇到了NodeJS语法错误,提示Await is only valid in async functions and the top level bodies of modules。我的代码里,seedUser是async函数,外层的await User.count()未报错,但map回调内的await User.create(user)触发该错误,想知道原因。
错误信息如下:
C:\node-project\api.testsite\seed\index.js:20
await User.create(user);
^^^^^SyntaxError: await is only valid in async functions and the top level bodies of modules
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1032:15)
at Module._compile (node:internal/modules/cjs/loader:1067:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object. (C:\node-project\api.testsite\database\connection.js:2:21)
at Module._compile (node:internal/modules/cjs/loader:1103:14)
我的代码如下:
const moment = require("moment"); const bc = require("bcryptjs"); var userList = require("./users"); var User = require("../app/Models/User"); module.exports = { seedUser: async function (db) { const Users = db.collection("users"); const userCount = await User.count(); if (userCount === 0) { userList.map((user) => { console.log(user, 'hioo') const DtCr = new Date(); user.created_date = DtCr; user.modified_date = DtCr; user.created_at = moment().valueOf(); user.updated_at = moment().valueOf(); console.log(user) await User.create(user); }); } } };
既然seedUser本身是async函数,为何只有map内的await报错?
原因分析与解决方案
原因
seedUser确实是async函数,但你传给map的回调函数是一个普通匿名函数,没有标记为async。await只能在async函数或模块顶级作用域中使用,所以这个回调里的await会触发语法错误。而外层的await User.count()直接在seedUser这个async函数内部执行,符合规则,因此不会报错。
解决方案
有两种常用修复方式,可根据需求选择:
方案1:使用Promise.all配合async回调的map
将map的回调改为async函数,再用Promise.all等待所有异步操作完成,适合需要并发创建用户的场景:
const moment = require("moment"); const bc = require("bcryptjs"); var userList = require("./users"); var User = require("../app/Models/User"); module.exports = { seedUser: async function (db) { const Users = db.collection("users"); const userCount = await User.count(); if (userCount === 0) { // 用Promise.all等待所有用户创建完成 await Promise.all(userList.map(async (user) => { console.log(user, 'hioo') const DtCr = new Date(); user.created_date = DtCr; user.modified_date = DtCr; user.created_at = moment().valueOf(); user.updated_at = moment().valueOf(); console.log(user) await User.create(user); })); } } };
方案2:使用for...of循环
如果需要按顺序创建用户(比如避免数据库并发压力),用for...of循环更直观:
const moment = require("moment"); const bc = require("bcryptjs"); var userList = require("./users"); var User = require("../app/Models/User"); module.exports = { seedUser: async function (db) { const Users = db.collection("users"); const userCount = await User.count(); if (userCount === 0) { // 按顺序遍历创建用户 for (const user of userList) { console.log(user, 'hioo') const DtCr = new Date(); user.created_date = DtCr; user.modified_date = DtCr; user.created_at = moment().valueOf(); user.updated_at = moment().valueOf(); console.log(user) await User.create(user); } } } };
内容的提问来源于stack exchange,提问作者Saswat

