在实例化一个类时,我遇到了一些异步等待的问题.我有一个User类,在实例化时,我希望自动散列密码并将其分配给密码.

class User {
    public userId: string;
    public password: string = '';

    constructor(public userName: string, public plainPassword: string, public email: string) {
        this.userId     = uuidv4()
        this.userName   = userName;
        this.email      = email.toLowerCase();
        this.hashPassword();
    }

    private async hashPassword(): Promise<void> {
        try {
            const salt = await bcrypt.genSalt(10);
            this.password = await bcrypt.hash(this.plainPassword, salt);
        } 
        catch (error) {
            throw error
        }
    }

散列密码不返回任何内容.但这是一个promise 功能,所以当我做测试时,我没有得到任何用户密钥……邮箱、密码、用户ID和用户名未定义...

你能帮帮我吗?

推荐答案

正如@akx所提到的,在脚本/类型脚本中使用异步构造函数是不可能的.但是,我们可以通过利用设计模式来绕过这一限制.

让我们探索两个快速的替代方案:

构建器模式

import { v4 as uuidv4 } from 'uuid';
import bcrypt from 'bcryptjs';

class User {
    public userId: string;
    public password: string = '';

    constructor(public userName: string, public plainPassword: string, public email: string) {
        this.userId = uuidv4();
        this.userName = userName;
        this.email = email.toLowerCase();
        this.plainPassword = plainPassword;
    }

    public async hashPassword(): Promise<void> {
        try {
            const salt = await bcrypt.genSalt(10);
            this.password = await bcrypt.hash(this.plainPassword, salt);
        } catch (error) {
            throw error;
        }
    }
}

class UserBuilder {
    private user?: User;

    public initialize(userName: string, plainPassword: string, email: string): UserBuilder {
        this.user = new User(userName, plainPassword, email);
        return this;
    }

    public async build(): Promise<User|null> {
        if (this.user) {
            await this.user.hashPassword();
            return this.user;
        }
        return null;
    }
}

async function clientCode() {
    const user = await new UserBuilder()
        .initialize('John Doe', 'password', 'name@email.com')
        .build();
        
    console.log(user);
}

clientCode();

工厂模式

import { v4 as uuidv4 } from 'uuid';
import bcrypt from 'bcryptjs';

class User {
    public userId: string;
    public password: string = '';

    private constructor(public userName: string, public plainPassword: string, public email: string) {
        this.userId = uuidv4();
        this.userName = userName;
        this.email = email.toLowerCase();
        this.plainPassword = plainPassword;
    }

    public async hashPassword(): Promise<void> {
        try {
            const salt = await bcrypt.genSalt(10);
            this.password = await bcrypt.hash(this.plainPassword, salt);
        } catch (error) {
            throw error;
        }
    }

    // factory method to create a User instance
    public static async createUser(userName: string, plainPassword: string, email: string): Promise<User> {
        const user = new User(userName, plainPassword, email);
        await user.hashPassword();
        return user;
    }
}

// Using the factory method
async function clientCode() {
    const user = await User.createUser('John Doe', 'password', 'name@email.com');
    console.log(user);
}

clientCode();

本质上,这两种模式都允许您控制实例化过程,从而增强代码的可读性和可维护性.虽然这些模式可能不能直接解决JavaScript/Type脚本中缺少异步构造函数的问题,但它们有效地解决了根本问题.

Javascript相关问答推荐

鼠标移动时更新画布

ReactJS中的material UI自动完成类别

React:未调用useState变量在调试器的事件处理程序中不可用

将json数组项转换为js中的扁平

IMDB使用 puppeteer 加载更多按钮(nodejs)

浮动Div的淡出模糊效果

为什么ngModel不能在最后一个版本的Angular 17上工作?'

Rehype将hashtag呈现为URL

WebRTC关闭navigator. getUserMedia正确

您能在卸载程序(QtInsteller框架)上添加WizardPage吗?

不能将空字符串传递给cy.containes()

try 使用javascript隐藏下拉 Select

在HTML语言中调用外部JavaScript文件中的函数

更新动态数据中对象或数组中的所有值字符串

如何使用TypeScrip设置唯一属性?

try 使用PM2在AWS ubuntu服务器上运行 node 进程时出错

我的NavLink活动类在REACT-ROUTER-V6中出现问题

输入数据覆盖JSON文件

将以前缓存的 Select 器与querySelector()一起使用

JSX/React -如何在组件props 中循环遍历数组