【问题标题】:Promise not terminating after reject() call拒绝()调用后承诺不会终止
【发布时间】:2020-06-13 00:13:35
【问题描述】:

您好,我正在尝试在执行数据库操作之前检查无效案例。出于某种原因,我的代码将运行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) new Promise() 包装器在这里是一个反模式。没有什么需要被承诺的。 (2)resolvereturn不一样。
  • @Roamer-1888 所以我应该放弃使用承诺的想法吗?我添加了我使用此功能的方式。
  • 不,只是放弃拥有new Promise() 包装器的想法。由于registerUser()async,它将(1) 自动将任何返回值包装在Promise 中,(2) 异步抛出,(3) 允许使用await
  • 也可以使用return reject()return resolve()。返回并阻止继续。
  • @NSTuttle,直截了当,但resolvereject 将在删除不必要的new Promise() 包装器时消失。

标签: typescript promise async-await


【解决方案1】:

async 函数中返回new Promise() 是一种反模式:async 函数已经返回一个promise,因此您只需要显式返回promise 应该解析的值到。

您描述的问题是由于您知道函数失败原因后没有退出函数造成的:如果您也没有returnthrow,该函数仍将继续其余代码.

解决这两个问题,您的代码可以重写如下:

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();
};

请注意,async 函数中的 throw 将使承诺(async 函数始终返回)以您提供的原因拒绝。

还要注意,在成功的情况下,分辨率值在这里是一个承诺(user.save()),这意味着async 函数的承诺会将其分辨率链接到 的分辨率em> 承诺。

【讨论】:

  • 总是抛出Error
  • 已更改。 Jeninja,请注意,在应用 Roamer 的建议后,您会得到错误实例的拒绝原因,而不是纯字符串。另见this advice
猜你喜欢
  • 2020-05-05
  • 1970-01-01
  • 2020-10-03
  • 2022-12-04
  • 2021-05-31
  • 2020-07-22
  • 2015-12-25
  • 2017-12-29
  • 2019-11-25
相关资源
最近更新 更多