最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - callback function access to closure variables? - Stack Overflow

programmeradmin4浏览0评论

The following piece of code has a bug but it opened an interesting question. Its using an angular's $http service which returns a promise. Once resolved, the callback function does not have access to the s1 variable.

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

    // show what's in
    for (var s=0;s<ids.length;s++) {
        var s1 = s;
        $http.get('/' + 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

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)

Can someone explains why?

thanks

Lior

The following piece of code has a bug but it opened an interesting question. Its using an angular's $http service which returns a promise. Once resolved, the callback function does not have access to the s1 variable.

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

    // show what's in
    for (var s=0;s<ids.length;s++) {
        var s1 = s;
        $http.get('http://mydomain./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

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)

Can someone explains why?

thanks

Lior

Share Improve this question edited Apr 30, 2013 at 17:26 Lior asked Apr 30, 2013 at 16:44 LiorLior 40.6k12 gold badges39 silver badges40 bronze badges 4
  • 1 I don't see any use of s1, where is the error happening? – Barmar Commented Apr 30, 2013 at 16:48
  • Your code doesn't reference s1 anywhere after it is defined. How can you be getting a reference error? – KevSheedy Commented Apr 30, 2013 at 16:52
  • i checked s1 in the debugger, while inside the callback. code edited. thanks for the remarks – Lior Commented Apr 30, 2013 at 17:24
  • 1 my mistake - when added properly with console.log it works. thanks! The lesson is, debugger cannot see closure variable unless they are explicit. – Lior Commented Apr 30, 2013 at 18:22
Add a ment  | 

1 Answer 1

Reset to default 9

This is a classic issue with asynchronous callbacks in a for loop. Both s and s1 are only declared once. Even though you declare var s1; within the loop, JavaScript has no block scope, so it's irrelevant.

This means all iterations share the same variables s and s1, so when the callback pletes, $scope.products[s] is looking up the ids.length + 1 product.

Instead, do:

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

function launchRequest(s) {
    $http.get('http://example./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.

发布评论

评论列表(0)

  1. 暂无评论