这个周在工作的时候遇到了一个奇怪的bug,找了很久,发现是并行计算的时候某个共享的对象变量会被篡改的原因
先直接上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| const Promise = require('bluebird'); const _ = require('loadsh');
function testForObject (obj, change) { console.log(`=====berfore: ${obj.test}=============`); obj.test = change; console.log(`=====after: ${obj.test}=============`); }
function testForCloneObject (obj, change) { let cloneObj = _.cloneDeep(obj); console.log(`=====berfore: ${cloneObj.test}=============`); cloneObj.test = change; console.log(`=====after: ${cloneObj.test}=============`); }
const start = async function () { const extParams = { test: 10 } const indexs = [1, 2]; Promise.map(indexs, (index) => { testForObject(extParams, index); }, {concurrency: 3}); }
const start2 = async function () { const extParams = { test: 10 } const indexs = [1, 2]; Promise.map(indexs, (index) => { testForCloneObject(extParams, index); }, {concurrency: 3}); }
start();
start2();
|
根据结果我们可以看到,如果传入的变量没有经过深复制,不同进程之间对于同一个传入的对象变量的修改会相互影响,这是因为在js中对象变量在传参时传入的是引用,所以如果你对于某个传入的对象参数直接修改,就会导致这种情况。
而且这种情况下,即使你传入的对象参数是const也是没有用的,因为const只是保证了该变量的引用地址是不变的,对于地址中保存的值是没有约束的。
最好的方法就是参数传入之后直接进行深复制。