【问题标题】:callback function access to closure variables?回调函数访问闭包变量?
【发布时间】:2013-04-24 16:12:03
【问题描述】:

以下代码有一个错误,但它提出了一个有趣的问题。它使用 Angular 的 $http 服务,它返回一个承诺。一旦解决,回调函数就无法访问 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 给出 ReferenceError: s1 is not defined in the debugger

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

有人能解释一下原因吗?

谢谢

里尔

【问题讨论】:

  • 我没有看到s1的任何用法,错误发生在哪里?
  • 您的代码在定义后不会在任何地方引用 s1。你怎么会得到一个参考错误?
  • 我在调试器中检查了 s1,而在回调中。代码编辑。感谢您的评论
  • 我的错误 - 当使用 console.log 正确添加时,它可以工作。谢谢!教训是,调试器无法看到闭包变量,除非它们是显式的。

标签: javascript angularjs closures promise


【解决方案1】:

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

...它在launchRequest 内部引入了一个新的函数级别范围,这意味着当回调解决时,s 在函数内部仍然是s

【讨论】:

  • 感谢@Matt,我了解 s,并感谢您的建议! (采取)。不过,在原始代码中,为什么 s1 在回调中不可见?我应该怎么做才能让 s1 在那里可见?
  • 好的 - 想通了。抱歉-我的错误。 s1 是可见的,只要你明确写出来。
猜你喜欢
  • 2013-04-24
  • 2014-06-24
  • 2021-05-28
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多