(节点:50868)UnhandledPromiseRejectionWarning:TypeError:无法读取null的属性“保存”

时间:2020-05-14 18:54:00

标签: javascript node.js mongodb mongoose save

因此,我试图在不协调的情况下创建一个简单的level-XP系统,该系统每次有人发送消息时都会升级。我在消息事件中将其用于关卡系统。级别定义为我使用猫鼬时的模式。有一个问题是它可以将其保存为没有数据的人,然后他们发送一条消息,创建XP之类的数据:0级:1,但是随后当他们发送诸如XP之类的消息时不再更新:25等。错误是(节点:50868)UnhandledPromiseRejectionWarning:TypeError:无法读取属性“保存”为null

level1.findOne({ guildID: message.guild.id, userID: message.author.id }, async (err, res) => {
  if(err) return console.error(err)

  if(!res) {
    let newdata = new level1({
      guildID: message.guild.id,
      userID: message.author.id,
      level: 1,
      xp: 0,
      totalxp: 0,
      time: Date.now()
    })

    newdata.save()
    res = newdata
  } else {

    if (message.content.startsWith(`${prefix}`)) return;

  const generate = Math.floor(Math.random() * 18);
    (await level1.findOneAndUpdate({ guildID: message.guild.id, userID: message.guild.id }, { totalxp: res.totalxp += generate, xp: res.xp + generate, time: Date.now() })).save()

  if(res.xp >= res.level * 300) {
    (await level1.findOneAndUpdate({ guildID: message.guild.id, userID: message.guild.id }, { level: res.level++, xp: 0 })).save()
    message.channel.send(`Congratulations you are now Level **${res.level}**, ${message.author}`);
  }
}

})

1 个答案:

答案 0 :(得分:1)

您无需将.save()添加到findOneAndUpdate

findOneAndUpdate将更新db中的记录,而无需使用.save()

因此您的更新查询应类似于

await level1.findOneAndUpdate(
    { guildID: message.guild.id, userID: message.guild.id }, // filter part
    { totalxp: res.totalxp += generate, xp: res.xp + generate, time: Date.now() } // update part
)

await level1.findOneAndUpdate(
    { guildID: message.guild.id, userID: message.guild.id },
    { level: res.level++, xp: 0 }
)

我认为这可以解决问题

关于代码的逻辑,我认为我们可以在更新查询之前使用某种逻辑将两个更新查询合并到一个查询中

我们可以在else部分中使用此逻辑

const generate = Math.floor(Math.random() * 18);

let updatePart = {
    totalxp: (res.totalxp || 0) + generate, // this will be updated in all cases, even if the level is upgraded or not
    time: Date.now() // this will also be updated in all cases
}

let msg = ''; // a message to be returned after the update

if (res.xp + generate >= res.level * 300) {
    // if experience + random generate is greater than level * 300, 
    // then we need to update the level, and set the xp to 0

    updatePart.level = res.level++;
    updatePart.xp = 0;

    // update the msg with the new level
    msg = `Congratulations you are now Level **${res.level++}**, ${message.author}`

} else {
    // if experience + random generate is lower than level * 300, this means the level is the same
    // then we need to update the xp only
    updatePart.xp = res.xp + generate;

    // update the msg
    msg = `Experience updated successfully`
}

// just do the update query once, 
// If we just need to update the document, 
// we can use updateOne instead of findOneAndUpdate

await level1.updateOne( // you can use findOneAndUpdate also, it's okay
    { guildID: message.guild.id, userID: message.guild.id }, // filter part
    updatePart // this is the update object
)

message.channel.send(msg);

希望有帮助