如何使用猫鼬多次正确触发模式方法

Posted

技术标签:

【中文标题】如何使用猫鼬多次正确触发模式方法【英文标题】:How to trigger schema methods multiple times correctly with mongoose 【发布时间】:2020-10-11 12:52:07 【问题描述】:

我试图触发用户方法两次,但猫鼬抱怨并行保存:

ParallelSaveError: Can't save() the same doc multiple times in parallel

awaitPromises-array 内部有两个相同的方法,我认为使用await Promise.all() 可以顺利进行。不幸的是,不可能预先将值相加以仅运行一次该方法。

长话短说:如何触发相同的用户方法两次而不遇到.save()-issue?

// User.js (Model)

const mongoose = require("mongoose");
const  Schema  = mongoose;

const userSchema = new Schema(
    account: 
        username: String,
        discordId: String
    ,
    stats: 
        attack: 50
    ,
    hero: 
        rank: 0,
        currentHealth: 100
    

userSchema.methods.loseHp = function(damage) 
    this.hero.currentHealth -= damage
    if (this.hero.currentHealth <= 0) 
        this.hero.currentHealth = 1
    
    return this.save();
;

module.exports = mongoose.model("User", userSchema);

// gameLogic.js
const calculateResult = async (player, enemy)=>
    const awaitPromises = [];

    for (let i = 0; i < enemy.allowedAttacks; i += 1)  // max 3 iterations
        awaitPromises.push(player.loseHp(Math.random()*enemy.stats.attack))
        
    
    try 
        await Promise.all(awaitPromises)
     catch(error)
        console.log('error: ', error)
    

【问题讨论】:

你真的不应该在每次攻击后save(),而应该在所有loseHp 调用之后只使用一次。那么你也不需要Promise.all 【参考方案1】:
    一个promise 立即开始执行,Promise.all 所做的只是返回一个promise,当所有传入的promise 都实现时(但那时它们可能已经实现了!)。如果 Mongoose 不喜欢运行中的同一模型的两个 Promise,您可能需要在循环中一个一个地执行它们:
await player.loseHp(Math.random()*enemy.stats.attack);
    为什么要多次拨打loseHp?你不能把伤害加起来,最后打一次loseHp吗?

【讨论】:

以上是关于如何使用猫鼬多次正确触发模式方法的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理猫鼬模式迁移?

如何正确处理猫鼬模式迁移?

如何正确处理猫鼬模式迁移?

猫鼬改变模式格式

如何在猫鼬中为 geojson 数据创建模式?

猫鼬使用方法将模式添加到模式中