一个困扰了我两天的异步 bug
问题最后定位在一个被提前释放的引用上,排查过程比修复本身花的时间长得多。记下排查思路,方便以后遇到类似情况能更快定位。
现象
接口偶尔返回一个已经不存在的对象数据,复现概率大概十分之一,日志里也看不出异常,一开始怀疑是并发写入的问题。
定位过程
加了几处时间戳日志之后发现,问题出在一个回调执行时,它引用的对象已经在另一个流程里被清理掉了:
js
function onDone(task) {
// task.result 有时候已经被上游清空
save(task.result)
}根本原因是两个流程共用了同一个对象引用,而不是各自持有一份拷贝。
之后养成的习惯是:跨异步边界传递的数据,能拷贝就不共享引用,哪怕多一点内存开销。
后续
把类似的几处共享引用都做了防御性拷贝,顺手补了一个单测覆盖这个场景。