Обещание не прекращается после вызова reject () - PullRequest
0 голосов
/ 29 февраля 2020

Привет. Я пытаюсь проверить недействительные случаи перед выполнением действия с базой данных. По какой-то причине мой код будет работать reject('Invalid E-mail address.');, но затем он также продолжит выполнять строку await User.findOne({email}). Есть несколько способов переписать это, но я хотел бы сохранить текущую структуру этого кода. Как я могу завершить функцию после отклонения и предотвратить запуск остальной части кода? Спасибо

user.database.ts

export const registerUser = async (email: string, password: string): Promise<User> => {
    return new Promise(async (resolve, reject) => {
        // check if email or password are null
        if (!email || !password) {
            reject('Invalid E-mail address or Password.');
        }

        // check if email is invalid
        if (!EmailValidator.validate(email)) {
            reject('Invalid E-mail address.');
        }

        // check if database already contains E-mail address
        await User.findOne({email}).then((user: any) => {
            if (user) {
                reject('E-mail address already in use.'); // code should stop here
            }
        });

        // anything below should not run

        // create user object
        const user = new User({
            _id: new mongoose.Types.ObjectId(),
            email: email,
            password: password
        });

        // save user object to database
        await user.save().then((result: any) => {
            resolve(result);
        }).catch((error: any) => {
            reject(error);
        });
    });
};

auth.controller.ts

export const register = (req: Request, res: Response) => {
    const email = req.body.email;
    const password = req.body.password;
    registerUser(email, password).then((user: User) => {
        res.status(200).json(user);
    }).catch((error: any) => {
        res.status(300).json(error);
    });
};

1 Ответ

2 голосов
/ 29 февраля 2020

Возвращение new Promise() внутри функции async является антипаттерном: async функция уже возвращает обещание, поэтому вам нужно только явно вернуть значение, которое обещание должно разрешить к.

Проблема, которую вы описываете, вызвана тем, что вы не выходите из своей функции, как только узнаете причину ее сбоя: функция все равно продолжит выполнение остальной части кода, если вы не сделаете этого. return или throw.

Для решения обеих проблем ваш код можно переписать следующим образом:

const registerUser = async (email: string, password: string): Promise<User> => {
    if (!email || !password) {
        throw new Error('Invalid E-mail address or Password.');
    }

    if (!EmailValidator.validate(email)) {
        throw new Error('Invalid E-mail address.');
    }

    let user: any = await User.findOne({email})
    if (user) {
        throw new Error('E-mail address already in use.');
    }

    user = new User({
        _id: new mongoose.Types.ObjectId(),
        email: email,
        password: password
    });

    return user.save();
};

Обратите внимание, что throw внутри функции async даст обещание (что async функция всегда возвращает) отклонить с указанием предоставленной вами причины.

Обратите также внимание, что в случае успеха значение разрешения здесь является обещанием (user.save()) , так что это означает, что обещание функции async свяжет ее разрешение с разрешением , которое обещает.

...