您如何实现发出异步数据库请求的 Sveltekit Post 端点?
How do you implement a Sveltekit Post endpoint which makes an async DB request?
因此,当我访问 SvelteKit post 端点时,如果我提交了一些值但它们没有通过验证检查,它工作正常。它 return 是正确的状态并且 body。但是,当它插入数据库时,端点 return 出现 404 错误,但它可以将用户插入数据库。我认为这是因为数据库调用是异步的并且 SvelteKit 没有等待结果 return,但不确定如何更改我的代码所以它等待并发送正确的 json 响应。
感谢您的帮助!
import type { EndpointOutput } from '@sveltejs/kit';
import bcrypt from 'bcrypt';
import { randomUUID } from 'crypto';
import db from '$lib/config/db.js';
import { roles } from '$lib/config/roles.js';
import validation from '$lib/_helpers/validation';
export async function post({
body
}: {
body: { firstName: string; lastName: string; emailAddress: string; password: string };
}): Promise<EndpointOutput> {
//lets trim any whitespace on the fields
console.log(body);
const firstName = body?.firstName.trim();
const lastName = body?.lastName.trim();
const email = body?.emailAddress.trim();
const password = body?.password.trim();
const userRole = roles.web + roles.anonymous;
const bcryptPassword = await bcrypt.hash(password, 10);
const emailToken = randomUUID();
// double check the validation on the fields in case user submits directly to this endpoint.
if (validation.validateEmail(email) == false) {
//console.log(email);
return {
status: 422,
body: {
message: 'Please enter a valid email address.'
}
};
}
if (validation.validatePassword(password) == false) {
return {
status: 422,
body: {
message: 'Password must be at least 6 characters.'
}
};
}
if (validation.validateNotEmpty(firstName) == false) {
return {
status: 422,
body: {
message: 'First Name is required.'
}
};
}
if (validation.validateDisplayName(lastName) == false) {
return {
status: 422,
body: {
message: 'Last Name is required.'
}
};
}
//insert user
await db.query(
'INSERT INTO users (first_name, last_name, email, user_password, user_role, email_verification_token) VALUES (, , , , , )',
[firstName, lastName, email, bcryptPassword, userRole, emailToken],
(error, results) => {
// console.log(error, results);
if (error) {
return {
status: 417,
body: {
message: error.toString()
}
};
}
//console.log(results);
return {
status: 201,
body: {
message: 'User created successfully'
}
};
}
);
}
更新修复
我最终使用 pg-promise 包而不是 pg 包来连接我的数据库。
以下是更新后的代码,以防有人遇到类似问题。
import type { EndpointOutput } from '@sveltejs/kit';
import bcrypt from 'bcrypt';
import { randomUUID } from 'crypto';
import { roles } from '$lib/config/roles.js';
import validation from '$lib/_helpers/validation';
import { db } from '$lib/config/db.js';
export async function post({
body
}: {
body: { firstName: string; lastName: string; emailAddress: string; password: string };
}): Promise<EndpointOutput> {
//lets trim any whitespace on the fields
console.log(body);
const firstName = body?.firstName.trim();
const lastName = body?.lastName.trim();
const email = body?.emailAddress.trim();
const password = body?.password.trim();
const userRole = roles.web + roles.anonymous;
const bcryptPassword = await bcrypt.hash(password, 10);
const emailToken = randomUUID();
// double check the validation on the fields in case user submits directly to this endpoint.
if (validation.validateEmail(email) == false) {
//console.log(email);
return {
status: 422,
body: {
message: 'Please enter a valid email address.'
}
};
}
if (validation.validatePassword(password) == false) {
return {
status: 422,
body: {
message: 'Password must be at least 6 characters.'
}
};
}
if (validation.validateNotEmpty(firstName) == false) {
return {
status: 422,
body: {
message: 'First Name is required.'
}
};
}
if (validation.validateDisplayName(lastName) == false) {
return {
status: 422,
body: {
message: 'Last Name is required.'
}
};
}
//check if user already exists.
const userAlreadyExists = await db.oneOrNone('SELECT email from users WHERE email= LIMIT 1', [
email
]);
console.log(' result: ' + userAlreadyExists);
if (userAlreadyExists) {
return {
status: 409,
body: {
message: 'User with that email already exists'
}
};
}
try {
// insert New user into DB
await db.none(
'INSERT INTO users (first_name, last_name, email, user_password, user_role, email_verification_token) VALUES (, , , , , )',
[firstName, lastName, email, bcryptPassword, userRole, emailToken]
);
return {
status: 201,
body: {
message: 'User created successfully'
}
};
} catch (error) {
return {
status: 417,
body: {
message: error.toString()
}
};
}
}
您的问题是您使用的数据库是通过回调系统实现的 function query(queryString, callback)
而您的 await
不会 wait,也不回调中的 return
实际上是端点之外的 return。
最好的办法是检查你的数据库库是否有异步方法,你可以在其中执行类似这样或类似的操作:
const { errror, result } = await db.query(....)
这样应用程序实际上会等待查询完成。
因此,当我访问 SvelteKit post 端点时,如果我提交了一些值但它们没有通过验证检查,它工作正常。它 return 是正确的状态并且 body。但是,当它插入数据库时,端点 return 出现 404 错误,但它可以将用户插入数据库。我认为这是因为数据库调用是异步的并且 SvelteKit 没有等待结果 return,但不确定如何更改我的代码所以它等待并发送正确的 json 响应。
感谢您的帮助!
import type { EndpointOutput } from '@sveltejs/kit';
import bcrypt from 'bcrypt';
import { randomUUID } from 'crypto';
import db from '$lib/config/db.js';
import { roles } from '$lib/config/roles.js';
import validation from '$lib/_helpers/validation';
export async function post({
body
}: {
body: { firstName: string; lastName: string; emailAddress: string; password: string };
}): Promise<EndpointOutput> {
//lets trim any whitespace on the fields
console.log(body);
const firstName = body?.firstName.trim();
const lastName = body?.lastName.trim();
const email = body?.emailAddress.trim();
const password = body?.password.trim();
const userRole = roles.web + roles.anonymous;
const bcryptPassword = await bcrypt.hash(password, 10);
const emailToken = randomUUID();
// double check the validation on the fields in case user submits directly to this endpoint.
if (validation.validateEmail(email) == false) {
//console.log(email);
return {
status: 422,
body: {
message: 'Please enter a valid email address.'
}
};
}
if (validation.validatePassword(password) == false) {
return {
status: 422,
body: {
message: 'Password must be at least 6 characters.'
}
};
}
if (validation.validateNotEmpty(firstName) == false) {
return {
status: 422,
body: {
message: 'First Name is required.'
}
};
}
if (validation.validateDisplayName(lastName) == false) {
return {
status: 422,
body: {
message: 'Last Name is required.'
}
};
}
//insert user
await db.query(
'INSERT INTO users (first_name, last_name, email, user_password, user_role, email_verification_token) VALUES (, , , , , )',
[firstName, lastName, email, bcryptPassword, userRole, emailToken],
(error, results) => {
// console.log(error, results);
if (error) {
return {
status: 417,
body: {
message: error.toString()
}
};
}
//console.log(results);
return {
status: 201,
body: {
message: 'User created successfully'
}
};
}
);
}
更新修复
我最终使用 pg-promise 包而不是 pg 包来连接我的数据库。
以下是更新后的代码,以防有人遇到类似问题。
import type { EndpointOutput } from '@sveltejs/kit';
import bcrypt from 'bcrypt';
import { randomUUID } from 'crypto';
import { roles } from '$lib/config/roles.js';
import validation from '$lib/_helpers/validation';
import { db } from '$lib/config/db.js';
export async function post({
body
}: {
body: { firstName: string; lastName: string; emailAddress: string; password: string };
}): Promise<EndpointOutput> {
//lets trim any whitespace on the fields
console.log(body);
const firstName = body?.firstName.trim();
const lastName = body?.lastName.trim();
const email = body?.emailAddress.trim();
const password = body?.password.trim();
const userRole = roles.web + roles.anonymous;
const bcryptPassword = await bcrypt.hash(password, 10);
const emailToken = randomUUID();
// double check the validation on the fields in case user submits directly to this endpoint.
if (validation.validateEmail(email) == false) {
//console.log(email);
return {
status: 422,
body: {
message: 'Please enter a valid email address.'
}
};
}
if (validation.validatePassword(password) == false) {
return {
status: 422,
body: {
message: 'Password must be at least 6 characters.'
}
};
}
if (validation.validateNotEmpty(firstName) == false) {
return {
status: 422,
body: {
message: 'First Name is required.'
}
};
}
if (validation.validateDisplayName(lastName) == false) {
return {
status: 422,
body: {
message: 'Last Name is required.'
}
};
}
//check if user already exists.
const userAlreadyExists = await db.oneOrNone('SELECT email from users WHERE email= LIMIT 1', [
email
]);
console.log(' result: ' + userAlreadyExists);
if (userAlreadyExists) {
return {
status: 409,
body: {
message: 'User with that email already exists'
}
};
}
try {
// insert New user into DB
await db.none(
'INSERT INTO users (first_name, last_name, email, user_password, user_role, email_verification_token) VALUES (, , , , , )',
[firstName, lastName, email, bcryptPassword, userRole, emailToken]
);
return {
status: 201,
body: {
message: 'User created successfully'
}
};
} catch (error) {
return {
status: 417,
body: {
message: error.toString()
}
};
}
}
您的问题是您使用的数据库是通过回调系统实现的 function query(queryString, callback)
而您的 await
不会 wait,也不回调中的 return
实际上是端点之外的 return。
最好的办法是检查你的数据库库是否有异步方法,你可以在其中执行类似这样或类似的操作:
const { errror, result } = await db.query(....)
这样应用程序实际上会等待查询完成。