回调函数访问闭包变量?

Lio*_*ior 3 javascript closures promise angularjs

下面这段代码有一个bug,但它开了一个有趣的问题.它使用angular的$ http服务返回一个promise.解析后,回调函数无权访问s1变量.

    var ids = [];
    ids = ['81074'];

    // show what's in
    for (var s=0;s<ids.length;s++) {
        var s1 = s;
        $http.get('http://mydomain.com/api/catalog/product/' + ids[s]).
                 success(function(data) {
        // console.log(s1); <--- reference error
            $scope.products[s].setProductData(data);

        }).error(function(err){
                console.log('--------- error',err);
            });
    };
Run Code Online (Sandbox Code Playgroud)

s1给出ReferenceError:调试器中未定义s1

有趣的是,它确实可以访问for循环变量s,它始终为1 - 正如预期的那样,因为promise在增加后得到解决(因此错误BTW)

有人能解释为什么吗?

谢谢

利奥尔

Mat*_*att 9

这是for循环中异步回调的经典问题.双方ss1只声明一次.即使你var s1;在循环中声明,JavaScript也没有块范围,所以它是无关紧要的.

这意味着所有的迭代共享相同的变量ss1,所以回调完成时,$scope.products[s]被仰视的ids.length + 1产品.

相反,做:

var ids = [];
ids = ['81074'];

function launchRequest(s) {
    $http.get('http://example.com/api/catalog/product/' + ids[s]).success(function (data) {
        $scope.products[s].setProductData(data);
    }).error(function (err) {
        console.log('--------- error', err);
    });
}

// show what's in
for (var s = 0; s < ids.length; s++) {
    launchRequest(s);
}
Run Code Online (Sandbox Code Playgroud)

...里面引入了一个新的函数级范围launchRequest,这意味着当回调结算时s仍然s在函数内部.