一个”简单”的需求
在与后端联调时,需要传递一个时间给后端,开发时没注意格式,在参数对象中直接传递了Date对象,结果后端接收到的数据格式不对,先看看后端接收到的数据格式是什么样的。
1 | { |
额,这不是调用toISOString
方法返回的ISO 8601 格式的字符串么。字面日期表示的日期时间,默认是UTC时间,所以需要转换为本地时间。所以后端使用也使用Date
对象来接收。并配合合适的解析器就肯定没问题。然后此时后端要求的日期时间格式却是当前时区yyyy-MM-dd HH:mm:ss
,所以需要转换一下。我也搞不明白为什么要这样,使用时间戳或者UTC时间不香吗?不过后端接口有要求,对于我来说这也是小菜一碟,都不用在业务代码中处理,在axios拦截器中处理一下就完事了。
先看转换代码
1 | function formatDate(data) { |
写完代码后,我信心满满,心想这回肯定没问题了,这种小case都不需要自测的对不对,直接提交代码测试
那么你来看看这段代码有什么问题吗?
能有什么问题对不对,检测到属性值如果是日期格式就返回接口要求的格式,能有什么问题呢,类似的代码又不是第一次写了。然而就是这种”简单”的需求,却让我踩了一个大坑。
Bug
在我的摸鱼时候,我收到了反馈,说我的代码有问题,后端接收到的数据格式依然不对。那怎么可能,但是事实胜于雄辩,我打开浏览器,打开控制台,执行了一下上面的代码,真的不对。日期依然是ISO 8601 格式的字符串。如此看来这个if条件为假了,那么问题出在哪里呢?那我倒要看看这个value到底是什么。不是日期对象么、
添加了句console.log(value, typeof value),发现value是ISO 8601 格式的字符串,不是日期对象。也就是说在JSON.stringify中,在调用replacer函数时,value已经是ISO 8601 格式的字符串了,而不是日期对象。这尼码不是坑爹么。为什么要这么设计。
解决方案
问题找到了,解决方案也就有了,既然在调用replacer函数时,value已经是ISO 8601 格式的字符串了,那么我就在上一层处理。机智如我呢。
1 | function formatDate(data) { |
代码可能不完善,但是对于当前需求来说,已经够用了。
总结
老实自测,不要偷懒。Js里看似简单的API, 其实背后都有很多逻辑细节,一不小心就会为自己的不扎实买单。
其实关于stringify处理Date对象的逻辑在mdn上也有说明,stringify在处理数据时会优先调用toJSON方法,而Date的toJSON方法返回的就是ISO 8601 格式的字符串。只怪自己没有仔细看。