记录一次vue 和 prisma的问题排查

项目背景: 前端使用vue 后端使用node
其中后端服务器框架用express orm框架使用prisma 数据库是mysql
前后端使用json传输数据

问题:

  1. 数据库BigInt报错TypeError: Do not know how to serialize a BigInt
    查了一下发现根本就不是问题 是一个历史遗留问题,然后chrome的程序员开玩笑就不给解析,但是实际上一行代码就解决问题了

    解决方案: 在用到BigInt的serialize之前 给BigInt换上新的toJSON()函数

    // 因为这里项目用的是express 所以就是在根目录项目启动文件app.js 中添加这行代码
    BigInt.prototype.toJSON = function() { return this.toString(); }
    
  2. vue里,发现vuex中返回的带小数点的(数据库里是Decimal类型)的数据全都变成undefined了
    一开始还以为是后端出问题了,后来才发现element-plus的组件报错说,期待数值0.4,却收到了字符串对象’0.4’
    回头一看后端返回的数据

    {
    	//...
    	hrRatio: "0.4"
    	//...
    }
    

    好家伙原来是后端返回成字符串了
    为什么会返回成字符串呢? 这里输出hrRatio的类型,发现竟然是Object,也不是String也不是Number,而是一种奇怪的值,
    记录一次vue 和 prisma的问题排查_第1张图片
    初步猜测是prisma自定义对象,数据库是prisma从mysql取过来的,看这样子 有s有e的,可能是科学计数法的Decimal
    在vscode中把hrRatio取到,然后鼠标移上去看对象类型,发现果然是Decimal.
    拿到这个Decimal一看
    记录一次vue 和 prisma的问题排查_第2张图片
    是个class,那就大概猜出来了,可能它的valueOf()返回的是String类型而不是Number类型的.
    点开源码,跳出来一个d.ts文件,一看果然是这样的

记录一次vue 和 prisma的问题排查_第3张图片
然后又发现原来人家有toNumber()啊…那序列化的时候还整成string类型…
记录一次vue 和 prisma的问题排查_第4张图片
唉到这里就一切明了了:
Prisma从MySQL取回的Decimal类型不是Number类型,而是一种Prisma内建类型,这种类型内部不是完整的数字,读取时需要通过函数专门函数去转换.
Prisma内部提供了toString()toNumber()两种转换的方式,但是在toJSON()valueOf()时默认转换成String类型,所以express在返回结果时,会自动把这种类型的变量序列化为hrRatio: "0.4"而不是hrRatio: 0.4,这样心心念念着Number的前端到手却变成了String,自然就会炸锅了.
解决方案:把Prisma内建的Decimal类型的原型里的toJSON()换掉,换成返回Number类型的函数(如果该valueOf()估计也是可以的,但是改valueOf()担心会波及到其他的地方)
跟上面一样,也是在express第一次序列化Decimal之前,把proto原型里的函数换掉

const { Decimal } = require("@prisma/client/runtime")

Decimal.prototype.toJSON = function () { return this.toNumber(); }

你可能感兴趣的:(javascript,mysql,node.js)