mar*_*vic 5 javascript rest express next.js
在 Next.js api 处理程序中组织代码的最佳实践是什么?我看了这个视频,他将所有 REST 路线放在两个文件中:
pages/api/users/index.ts处理所有不需要的id操作GET /api/users - get all usersPOST pages/api/users - create a new user
pages/api/users/[id].ts处理所有需要idso GET api/users/1 - get user by id、PUT /api/users/1 - update user和 的操作DELETE /api/users/1 - delete a user
这意味着大量代码将进入 2 个文件并由一条switch case语句处理。所有这些代码应该如何组织?
每个case语句都应该有自己的try catch块来处理数据库调用,这会大量重复,我可以将单个语句try catch全部封装起来switch,但这会包装很多不必要的代码,也许每个语句都case需要不同的处理?我可以将 single 放在try catch高阶函数中并用它包装每个 case 块,但我不确定这也很好吗?
另外,稍后我将需要使用中间件来保护一些路由withProtected,withRole但这并不容易,因为现在多个 api 是在单个处理程序调用中处理的。
组织这个活动的最佳方式是什么?是否已经存在很好的完整示例?
// pages/api/users/index.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { hash } from 'bcryptjs';
import prisma from 'lib/prisma';
/**
* POST /api/users
* Required fields in body: name, username, email, password
*/
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<void> {
const { method, body } = req;
switch (method) {
case 'GET':
// get all
// try catch again?
const users = await prisma.user.findMany();
res.status(200).json({ users });
break;
case 'POST':
// create
try {
const { name, username, email, password: _password } = body;
// todo: validate...
const _user = await prisma.user.findFirst({
where: { email },
});
if (_user)
throw new Error(`The user with email: ${email} already exists.`);
const password = await hash(_password, 10);
const user = await prisma.user.create({
data: {
name,
username,
email,
password,
},
});
res.status(201).json({ user });
} catch (error) {
res.status(500).json({ error });
}
break;
default:
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我做事的方式。它还涵盖 method not allowed
我的项目中的工作代码示例
/**
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {{[key: string]: () => Promise<void>}} actions
*/
export default async function globalAPICall(req, res, actions) {
try {
const method = req.method
// check an action exists with request.method else throw method not allowed
if (!Object.keys(actions).includes(method)) {
console.log('method not allowed')
throw new MyError('Method not allowed', 405)
}
// run the action matching the request.method
await actions[method]()
} catch(err) {
if (err instanceof MyError) {
res.status(err.code).send(err.message);
} else {
res.status(500).send("Internal server error");
}
}
}
Run Code Online (Sandbox Code Playgroud)
/**
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
*/
export default async function handler(req, res) {
async function POST() {
const { email, password, username } = req.body;
if (!username) {
throw new MyError('Username required', 400)
}
await CreateUser(email, password, username)
res.status(201).send();
}
async function GET() {
const result = await ListUsers()
res.status(200).json(result);
}
await globalAPICall.js(req, res, {POST, GET})
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3290 次 |
| 最近记录: |