2013-07-01 19 views
1

如果我叫测试(3)我得到警报,消息1递归方法决策问题的事件

function test(param) { 

    var tt = [ "a", "b", "c" ]; 
    for (var i = 0; i < param; i++) { 
     if (tt[i] == "b") { 
      test(1); 
      alert(i); 
     } 
    } 
} 

,但它不是在成功事件正常工作。如果我在方法测试(3)下面打电话,请考虑从请求中获得成功。我收到警报,消息3

function test(param) { 

    var tt = [ "a", "b", "c" ]; 
    for (var i = 0; i < param; i++) { 
     if (tt[i] == "b") { 
      Ext.Ajax.request({ 
       url : 'test.do', 
       method : 'POST', 
       success : function(response) { 
        test(1); 
        alert(i); 
       } 
      }); 
     } 
    } 
} 
+1

可能会重复http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – rab

+0

感谢您的回复rab。但对于我来说,第一个功能工作正确(这确定范围是正确的)。只有当我在事件中使用“我”时才有问题。 –

回答

0

好吧,这是你的代码:http://jsfiddle.net/848AE/1/

看在控制台(我改变成功事件失败,但它并不重要)。

function test(param) { 
    console.log('------------------------------'); 
    console.log('param = ' + param); 
    var tt = [ "a", "b", "c" ]; 
    for (var i = 0; i < param; i++) { 
     console.log('Before if-check, i = ' + i); 
     if (tt[i] == "b") { 
      console.log('Request start, after if-check i = ' + i); 
      Ext.Ajax.request({ 
       url : 'test.do', 
       method : 'POST', 
       failure: function(response) { 
        console.log('Failure start, i = ' + i); 
        test(1); 
        console.log('Alert(i) = ' + i); 
       } 
      }); 
      // break; 
     } 
    } 
} 

test(3); 

日志从第一码(在没有休息周期字):

------------------------------ 
param = 3 
Before if-check, i = 0 
Before if-check, i = 1 
Request start, after if-check i = 1 
Before if-check, i = 2 
POST http://fiddle.jshell.net/_display/test.do 404 (NOT FOUND) ext-all.js:21 
Failure start, i = 3 
------------------------------ 
param = 1 
Before if-check, i = 0 
Alert(i) = 3 

正如你所看到的,当你开始请求,功能并没有停止执行,并继续工作的周期(我= 2,3)。所以,当你从服务器获得响应时,变量i的值为3.

然后,您调用具有参数1的函数,它完成并返回失败函数,但在失败函数范围内,变量i的值仍然为3

因此,如果我理解你的话,你必须在代码注释中添加循环中的break字。

编辑:

如果你喜欢与暂停,直至回调执行,以执行在循环请求,有没有记录属性:

var response = Ext.Ajax.request({ 
    ... 
    async: false, 
    ... 
}) 

结果与异步:假:

param = 3 
Before if-check, i = 0 
Before if-check, i = 1 
Request start, after if-check i = 1 
POST http://fiddle.jshell.net/_display/test.do 404 (NOT FOUND) ext-all.js:21 
Failure start, i = 1 
------------------------------ 
param = 1 
Before if-check, i = 0 
Alert(i) = 1 
Before if-check, i = 2 
+0

谢谢Fsou1。我很清楚你的答案。但我怎么能暂停循环直到事件得到执行。 –

+1

编辑有关暂停循环的问题的答案;) – FSou1

+0

非常感谢您的帮助。但async:false属性不适合我。我使用的是extjs 3.2。 –

3

你需要把i放在一个封闭物周围你的异步函数调用。您可以通过使用IIFE认识到这一点,创建for循环内的范围,其中的i值保留:

for (var i = 0; i < param; i++) { 
    if (tt[i] == "b") { 
     (function(i){ 
      Ext.Ajax.request({ 
       url : 'test.do', 
       method : 'POST', 
       success : function(response) { 
        test(1); 
        alert(i); 
       } 
      }); 
     }(i)); 
    } 
} 

但它看起来像,你只需要i的警报消息,其可能仅用于调试目的。所以如果一切正常,并且你真的不需要在回调函数(success)中访问i,那么你也不需要额外的范围。

+0

谢谢Basilikum。我并不担心警惕。我正在为表单创建动态组件。在这种形式中,我得到了fieldset(它又包含动态组件)。这就是为什么我需要递归功能。如果成功,生病将得到fieldset的组件。编码太大,这就是为什么我提出样本问题。 –

+1

@basilikum有没有关于这个问题的好文章?我对这些示波器的工作方式感兴趣 – casraf

+1

@ChenAsraf你只需要理解在JavaScript中创建新范围的唯一表达式就是一个函数。在我的例子中,它只是一个函数,它立即调用它自己,并将'i'的当前值传递给它自己,以便在函数体内定义一个新变量'i'。我不太确定文章。只要谷歌“JavaScript函数范围”或“JavaScript IIFE”,如果你特别感兴趣这些类型的功能。尽管如此,下面是我很快找到的一篇文章,它可能对你很有趣:http://tinyurl.com/2gxrzdh – basilikum