typescript - Kuinka toteutat Sveltekit Post-päätepisteen, joka tekee asynkronisen tietokantakyselyn?


Joten kun käytän SvelteKitin post-päätepistettä, se toimii hyvin, jos lähetän joitakin arvoja eivätkä ne läpäise validointitarkistuksia. Se palauttaa oikean tilan ja sisällön. Kuitenkin kun se tekee tietokantaan lisäyksen, päätepiste palauttaa 404-virheen, mutta lisää käyttäjän tietokantaan oikein. Oletan, että syy on se, että tietokantakutsu on asynkroninen ja SvelteKit ei odota tuloksen palautumista, mutta en ole varma, miten muuttaa koodiani niin, että se odottaa ja lähettää oikean JSON-vastauksen.

Kiitos kaikesta avusta!

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 ($1, $2, $3, $4, $5, $6)',
        [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'
                }
            };
        }
    );
}

PÄIVITYS KORJAUS

Päädyin käyttämään pg-promise-pakettia pg-paketin sijaan yhdistääkseni tietokantaani.

Alla on päivitetty koodi siltä varalta, että jollekulla on samanlainen ongelma.

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=$1 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 ($1, $2, $3, $4, $5, $6)',
            [firstName, lastName, email, bcryptPassword, userRole, emailToken]
        );

        return {
            status: 201,
            body: {
                message: 'User created successfully'
            }
        };
    } catch (error) {
        return {
            status: 417,
            body: {
                message: error.toString()
            }
        };
    }
}

Vastaus #1

Ongelmasi on se, että käyttämäsi tietokanta on toteutettu takaisinsoittojärjestelmällä function query(queryString, callback) eikä sinun await odota sitä, eikä myöskään return takaisinsoitossa ole oikeasti paluu endpointistasi.

Paras tapa on tarkistaa, onko tietokantakirjastossasi asynkronista menetelmää, jossa voit tehdä jotain tällaista tai vastaavaa:

const { errror, result } = await db.query(....)

Tällä tavalla sovellus todella odottaa kyselyn valmistumista.