提问人:Minimuscle 提问时间:7/25/2022 最后编辑:Apoorva ChikaraMinimuscle 更新时间:7/25/2022 访问量:973
Node.js Express 不等待异步等待
Node.js Express not waiting for Async Await
问:
我有一个程序正在尝试运行,在获取汽车时,它需要等待函数完成才能运行结果,但它似乎不起作用。我是新手,所以我真的不知道我做得那么好。
app.get('/cars', async (req, res) => {
try {
const result = await getCars()
console.log('result: ' + result)
res.send(result)
} catch(error) {
console.log(error)
}
})
这是调用“getCars”函数的代码,如下所示:
const getCars = async () => {
// TODO: Replace this with a call to the database
await fs.readFile(__dirname + '/cars.json', function (err, data) {
if (err) {
throw err
}
let cars = JSON.parse(data)
//Groups the cars to their location, to be sorted and chosen based on arrivalDate
const groupBy = (xs, f) => {
return xs.reduce(
(r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r),
{}
)
}
const result = groupBy(cars, (c) => c.locationName)
Object.keys(result).forEach((car) => {
console.log(car)
// filters out cars with no arrival dates
let filtered = result[car].filter(obj => Object.keys(obj).includes("arrivalDate"));
//Sort cars by the last update time
filtered.sort(function (a, b) {
let keyA = new Date(a.arrivalDate.toString().split(' ')[0]),
keyB = new Date(b.arrivalDate.toString().split(' ')[0])
// Compare the 2 dates
if (keyA < keyB) return -1
if (keyA > keyB) return 1
return 0
}).reverse()
//Add the top two (latest) of each car to the new array
emailCars = [...emailCars, { [car]: [ result[car][0], result[car][1] ]}]
})
console.log('returning' + emailCars)
return emailCars
})
}
我在这里缺少什么来确保由函数设置,然后在用户转到 /cars 时发送给用户emailCars
答:
2赞
srigi
7/25/2022
#1
我相信问题出在函数的第一行......getCars()
await fs.readFile(__dirname + '/cars.json', function (err, data) {
}
您不能等待在回调中返回结果的函数。使用 readFile 的“sync”版本并从中删除 await/async,或者使用 readFile 的混合版本:getCars()
try {
const data = await fs.promises.readFile(filepath, 'utf8');
} catch (e) {
// handle errors herer
}
评论
0赞
Minimuscle
7/25/2022
如果我这样做,它会返回所有排序的数据,但我只需要对象中每个子数组的前 2 个(这就是所做的,只获取每个数组中的前 2 个对象)。还是我应该在 /get 函数中执行此操作?emailCars
0赞
aybasaran10
7/25/2022
#2
首先应了解同步/异步概念。这是我的解决方案。
import express from 'express'
import { readFile } from 'fs'
import { dirname } from 'path'
import { fileURLToPath } from 'url'
import { promisify } from 'util'
const app = express()
const readFileAsync = promisify(readFile)
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const getCars = async () => {
const file = await readFileAsync(`${__dirname}/cars.json`, 'utf8')
const cars = JSON.parse(file)
// DO YOUR LOGIC HERE
return cars
}
app.get('/', async (req, res) => {
try {
const cars = await getCars()
res.json(cars)
} catch (error) {
console.log(error)
}
})
app.listen(7777, () => {
console.log('Example app listening on port 7777!')
})
1赞
Apoorva Chikara
7/25/2022
#3
我看到的唯一问题是您将 async/await 与回调概念混合在一起。只需将所有回调替换为 async/await 并将它们包装在 try/catch 周围即可。
const getCars = async () => {
// TODO: Replace this with a call to the database
try {
const data = await fs.readFile(__dirname + '/cars.json')
let cars = JSON.parse(data)
//Groups the cars to their location, to be sorted and chosen based on arrivalDate
const groupBy = (xs, f) => {
return xs.reduce(
(r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r),
{}
)
}
const result = groupBy(cars, (c) => c.locationName)
Object.keys(result).forEach((car) => {
console.log(car)
// filters out cars with no arrival dates
let filtered = result[car].filter(obj => Object.keys(obj).includes("arrivalDate"));
//Sort cars by the last update time
filtered.sort(function (a, b) {
let keyA = new Date(a.arrivalDate.toString().split(' ')[0]),
keyB = new Date(b.arrivalDate.toString().split(' ')[0])
// Compare the 2 dates
if (keyA < keyB) return -1
if (keyA > keyB) return 1
return 0
}).reverse()
//Add the top two (latest) of each car to the new array
emailCars = [...emailCars, { [car]: [ result[car][0], result[car][1] ]}]
})
console.log('returning' + emailCars)
return emailCars
} catch (e) {
console.log(e);
}
}
如果您在理解此概念时遇到任何困难,请查看此链接。
如果我这样做,它会返回所有排序的数据,但我只需要 对象中每个子数组的前 2 个(这就是 emailCars 确实,只获取每个数组中的前 2 个对象)。或者我应该做 而不是在 /get 函数中?
任何实用程序函数都应正确组织,以保持应用程序的正确结构。路由不应该包含太多逻辑,逻辑应该放在控制器或类似的东西下。
您需要设计自己的逻辑,如果您遇到任何问题,欢迎您在此平台上提问。
评论
0赞
Minimuscle
7/25/2022
这奏效了,虽然我用了后者,但后者不起作用,但前者起作用了。我以前从未使用过 FS,但我现在更了解它了。谢谢fs.readFileSync
await fs.readFile
0赞
Apoorva Chikara
7/25/2022
这是因为您需要获取基于 promise 的 fs.readfile,它将按预期工作。将阻止您的后续请求,而您不想要它。readFileSync
评论