Promise.all未按预期执行,常量值意外累加问题求助
为什么Promise.all返回的结果中常量值出现累加?
我一看你这个问题就知道是对象引用传递在搞鬼!你期望每次调用testFN都基于初始的{"constant":"x"}生成新值,但实际上所有调用都在修改同一个对象,导致了累加的结果。
先给你拆解问题根源:
- 你定义的
var blob = {"constant":"x"};是一个对象,在JavaScript里,对象属于引用类型——当你把它作为参数传给testFN时,传递的不是对象的副本,而是指向这个对象的内存地址。 - 然后在
testFN里写的var newBlob = blob;根本没有创建新对象,只是让newBlob和blob指向了同一个内存里的对象。所以每次执行newBlob.constant = blob.constant+array.num,都是在修改原始blob对象的constant属性。
具体执行顺序一目了然:
- 第一次调用
testFN:原始blob.constant是x,修改后变成x1,此时全局的blob已经被改变 - 第二次调用
testFN:此时blob.constant已经是x1,加上2就变成x12 - 第三次调用:
blob.constant是x12,加上3变成x123
这就是为什么你打印出来的是累加后的结果——所有testFN共享了同一个blob对象的引用。
解决方案:创建对象的独立副本
你只需要保证每次调用testFN时,传入的是一个新的对象副本,而不是同一个引用。有两种常用方式:
方式1:在调用testFN时创建副本
修改forEach里的代码,用对象展开运算符或者Object.assign生成新对象:
Object.keys(arr).forEach(function(key, i) { // 使用对象展开运算符创建新副本 fnArr.push(testFN({...blob}, arr[key], i)); // 或者用Object.assign实现同样效果 // fnArr.push(testFN(Object.assign({}, blob), arr[key], i)); });
方式2:在testFN内部创建副本
如果你不想修改调用的地方,也可以在testFN里生成新对象:
function testFN(blob, array, iter){ // 创建传入blob的副本,而非直接引用原始对象 var newBlob = {...blob}; // 或者用Object.assign({}, blob) newBlob.constant = blob.constant + array.num; console.log(newBlob); return products.findOneAndUpdate(....); }
这样每个testFN操作的都是独立的对象,不会互相干扰,就能得到你期望的x1、x2、x3结果了。
内容的提问来源于stack exchange,提问作者SteveW
相关产品推荐
相关产品推荐

