How to structure javascript callback so that function scope is maintained properly

后端 未结 4 505
小蘑菇
小蘑菇 2020-12-13 02:56

I\'m using XMLHttpRequest, and I want to access a local variable in the success callback function.

Here is the code:

function getFileContents(filePat         


        
4条回答
  •  自闭症患者
    2020-12-13 03:32

    With the code you have provided test will still be in scope inside the callback. xhr will not be, other than xhr.responseText being passed in as data.

    Updated from comment:

    Assuming your code looks something like this:

    for (var test in testers)
      getFileContents("hello"+test+".js", function(data) {
        alert(test);
      });
    }
    

    As this script runs, test will be assigned the values of the keys in testers - getFileContents is called each time, which starts a request in the background. As the request finishes, it calls the callback. test is going to contain the FINAL VALUE from the loop, as that loop has already finished executing.

    There is a technique you can use called a closure that will fix this sort of problem. You can create a function that returns your callback function, creating a new scope you can hold onto your variables with:

    for (var test in testers) {
      getFileContents("hello"+test+".js", 
        (function(test) { // lets create a function who has a single argument "test"
          // inside this function test will refer to the functions argument
          return function(data) {
            // test still refers to the closure functions argument
            alert(test);
          };
        })(test) // immediately call the closure with the current value of test
      );
    }
    

    This will basically create a new scope (along with our new function) that will "hold on" to the value of test.

    Another way of writing the same sort of thing:

    for (var test in testers) {
      (function(test) { // lets create a function who has a single argument "test"
        // inside this function test will refer to the functions argument
        // not the var test from the loop above
        getFileContents("hello"+test+".js", function(data) {
            // test still refers to the closure functions argument
            alert(test);
        });
      })(test); // immediately call the closure with the value of `test` from `testers`
    }
    

提交回复
热议问题