Estoy escribiendo un Discord Bot en NodeJS y actualmente estoy experimentando un problema muy extraño.
Lo que quiero hacer es obtener el resultado de la salud a través del método getHP(), luego actualizando la propiedad de salud con el método setHP().
Esto funciona para una clase, pero no para otra. Entonces, básicamente, el código es prácticamente el mismo, pero para la otra clase no actualiza la propiedad.
Llamo a ambas clases sus métodos setHP() en sus constructores.
// Player.js - This works and displays: { current: 98, max: 98 } class Player { constructor(member, msg) { this.member = member this.msg = msg this.setHP() } health = {} setHP() { this.getHP.then(hp => { this.health = { current: hp.current, max: hp.current } }) } get getHP() { return new Promise(async (resolve) => { const stats = await this.stats resolve(stats.find(stat => stat.id === 'health')) }) } get stats() { return new Promise(async (resolve) => { const result = await DB.query(`select stats from members where member_id = ${this.member.id} `) resolve(JSON.parse(result[0][0].stats)) }) } get difficulty() { return new Promise(async (resolve) => { const result = await DB.query(`select difficulty from members where member_id = ${this.member.id} `) resolve(result[0][0].difficulty) }) } } // Enemy.js - Doesn't work and displays: {} class Enemy { constructor(player) { this.player = player this.setHP() } hp = {} setHP() { this.getHP.then(int => { this.hp = { current: int, max: int } }) } get getHP() { return new Promise(async (resolve) => { const difficulty = await this.player.difficulty const int = Math.floor(this.player.health.current * (difficulty * (Math.random() * 0.10 + 0.95))) resolve(int) }) } // minion_fight.js - Where the classes are used const Enemy = require("Enemy.js") const Player = require("Player.js") module.exports.execute = async (msg) => { const player = new Player(msg.member, msg) const enemy = new Enemy(player) // ... }El problema principal es que la instancia del jugador tiene una promesa pendiente que eventualmente se resolverá y establecerá la propiedad de health del jugador. Pero antes de que eso suceda, se crea la instancia enemiga y accede a la propiedad de health mencionada anteriormente del jugador dado antes de que se haya configurado. Por lo tanto, esta this.player.health.current no se puede evaluar.
Es mejor:
new Promise , cuando ya hay una promesa que esperar. Este es un anti-patrón.Aquí está la corrección sugerida, pero no la probé, así que espero que al menos entiendas la esencia de los cambios propuestos:
// Player.js class Player { constructor(member, msg) { this.member = member; this.msg = msg; } health = {} async setHP() { const hp = await this.getHP(); this.health = { current: hp.current, max: hp.current }; return this.health; } async getHP() { const stats = await this.stats(); return stats.find(stat => stat.id === 'health'); } async stats() { const result = await DB.query(`select stats from members where member_id = ${this.member.id} `); return JSON.parse(result[0][0].stats); } async difficulty() { const result = await DB.query(`select difficulty from members where member_id = ${this.member.id} `); return result[0][0].difficulty; } } // Enemy.js class Enemy { constructor(player) { this.player = player; } hp = {} async setHP() { const current = await this.getHP(); this.hp = { current, max: int }; return this.hp; } async getHP() { const playerHealth = await this.player.getHP(); // To be sure the promise is resolved! const difficulty = await this.player.difficulty(); return Math.floor(playerHealth.current * (difficulty * (Math.random() * 0.10 + 0.95))); } } // minion_fight.js const Enemy = require("Enemy.js") const Player = require("Player.js") module.exports.execute = async (msg) => { const player = new Player(msg.member, msg); const enemy = new Enemy(player); await enemy.setHP(); // ... }