承诺和参考价值



我想用angular构建一个承诺链来应用一组查询:

           for(variableIndex in _editableVariable.values) {
                var v = _editableVariable.values[variableIndex];
                if(v.value != v.old_value) {
                    console.log('v', v);
                    var newVariableRes = new VariableValueRes(v);
                    if(v.old_value == undefined) {
                        p.then(function() {
                            console.log('B', newVariableRes);
                            return newVariableRes.$save().$promise;
                        });
                    } else {
                        console.log('Try update: ', v);
                        p.then(function() {
                            console.log('C', newVariableRes);
                            return newVariableRes.$update().$promise;
                        });
                    }
                }
            }

我的问题是当我显示console.log('v',v)时,我得到了不同变量的不同value。当我在承诺中并显示console.log('B', newVariableRes)时,newVariableRes的内容是最新变量的value

输出示例:

v 
Object {value: "1", old_value: undefined, platform: "/api/v1/platform/1", product_variable: "/api/v1/product_var/2"}
v 
Object {value: "2", old_value: undefined, platform: "/api/v1/platform/2", product_variable: "/api/v1/product_var/2"}
v 
Object {value: "3", old_value: "", id: 7, platform: "/api/v1/platform/3", product_variable: "/api/v1/product_var/2"}
B 
Resource {value: "3", old_value: "", id: 7, platform: "/api/v1/platform/3", product_variable: "/api/v1/product_var/2"…}
B 
Resource {value: "3", old_value: "", id: 7, platform: "/api/v1/platform/3", product_variable: "/api/v1/product_var/2"…}
C 
Resource {value: "3", old_value: "", id: 7, platform: "/api/v1/platform/3", product_variable: "/api/v1/product_var/2"…}

由于我是javascript的新手,我认为v是对值的引用。因此,VariableValueRes采用了这个参考。当我更改v的指向引用时,这应该不会改变VariableValueRes的内容。

我的误会在哪里?

我认为问题是JS只有全局或函数作用域。因此,您的vnewVariableRes变量(在 for 循环中声明)被视为与声明为周围函数的顶部相同。

循环的每次迭代,v的值都会立即更新并记录,显示预期看到的值。但是,当您的 promise 回调执行时,循环已经完成,因此vnewVariableRes将保存其中的最后一个值。

这些回调通过闭包引用newVariableRes,这意味着外部函数可以完成,内部函数(您的回调)仍然使用外部作用域中此变量的值,而不是使用创建函数时存在的任何值。

这是在JS代码中看到的一个非常常见的错误,通常解决方案是通过将其放入新的函数作用域来修复变量,如下所示

p.then((function(nvr) {
    return function() {
        console.log('B', nvr);
        return nvr.$save().$promise;
    };
})(newVariableRes));

通过这种方式,我们创建一个函数,将其作为参数提供给我们的变量。由于我们不会在函数中更改此参数,因此我们的回调可以通过闭包使用它并确保它不会更改。

一种更简单的方法,因为您已经在使用 angular,是用 angular.forEach 替换您的 for 循环,这将以与 v 完全相同的方式解决此问题。现在您知道v回调中最初期望的,您可以在这些回调中创建new VariableValueRes(v),而不必担心newVariableRes指向什么(因为您不会使用它)。

最新更新