简体   繁体   English

回调函数访问闭包变量?

[英]callback function access to closure variables?

The following piece of code has a bug but it opened an interesting question. 下面这段代码有一个bug,但它开了一个有趣的问题。 Its using an angular's $http service which returns a promise. 它使用angular的$ http服务返回一个promise。 Once resolved, the callback function does not have access to the s1 variable. 解析后,回调函数无权访问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);
            });
    };

s1 gives ReferenceError: s1 is not defined in the debugger s1给出ReferenceError:调试器中未定义s1

And interestingly, it does have access to the for loop variable s, which is always 1 - as expected, since the promise got resolved after its incremented (hence the bug BTW) 有趣的是,它确实可以访问for循环变量s,它始终为1 - 正如预期的那样,因为promise在增加后得到解决(因此错误BTW)

Can someone explains why? 有人能解释为什么吗?

thanks 谢谢

Lior 利奥尔

This is a classic issue with asynchronous callbacks in a for loop. 这是for循环中异步回调的经典问题。 Both s and s1 are only declared once. ss1都只声明一次。 Even though you declare var s1; 即使你声明var s1; within the loop, JavaScript has no block scope, so it's irrelevant. 在循环中,JavaScript没有块范围,所以它是无关紧要的。

This means all iterations share the same variables s and s1 , so when the callback completes, $scope.products[s] is looking up the ids.length + 1 product. 这意味着所有迭代共享相同的变量ss1 ,因此当回调完成时, $scope.products[s]正在查找ids.length + 1产品。

Instead, do: 相反,做:

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);
}

... which introduces a new function level scope inside launchRequest , which means s is still s inside the function when the callback resolves. ......这里面引入了新的功能级别范围launchRequest ,这意味着s仍然是s函数内部时,回调解析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM