迭代期间的回调范围

callback scope during iteration

本文关键字:回调 范围 迭代      更新时间:2023-09-26

我知道有很多关于回调、作用域和闭包的问题。如果这是重复的,我提前道歉。

我有一个each循环,它调用一个函数,该函数执行几个异步操作,然后发出一个回调。当回调触发时,我失去了作用域(很明显)。我所做的就是将循环中的项传递给函数,然后在回调中返回它,这样我就有了我需要的作用域。这是最好的方法吗?我不想找太复杂的东西。我只是想确保我不会遇到任何"陷阱"。

function doSomething(varA, varB, self, callback) {
  // do a lot of ajax stuff
  callback(varA + varB, self);
}
$.each( $('.selected'), function(i, item) {
  doSomething('a', 'b', item, function(retVal, self) {
    // process retVal and self
  }
}

你得到的看起来很好,但有一件事:使用$.each()而不是.each()。试试这个:

$('.selected').each(function(i, item) {
  doSomething('a', 'b', item, function(retVal, self) {
    // process retVal and self
  }
}

如果你不需要 doSomething里面的元素引用,你可以这样创建一个闭包,稍微整洁一点:

function doSomething(varA, varB, callback) {
  // do a lot of ajax stuff
  callback(varA + varB);
}
$.each( $('.selected'), function() {
  var self = this;
  doSomething('a', 'b', function(retVal) {
    // process retVal and self
  }
});

人们在ajax和循环中遇到的主要"问题"是试图重用稍后执行的函数中的迭代变量。例如

for (var i in col) {
  $.ajax({
    url: '...' + i + '.html',
    success: function() {
      console.log(i);  // Why is i different???
    }
  });
}

出现这个"gotcha"是因为在所有success回调中共享了一个i实例。

在你的场景中,每个"迭代"关卡都有一个i。所以这个陷阱不会打到你。

由于callback是在.each()函数中定义的,因此当您到达回调函数时,item仍然在范围内。因此,如果doSomething()从不使用self,则不需要传递它。你可以直接引用item:

function doSomething(varA, varB, callback) {  
  // do a lot of ajax stuff  
  callback(varA + varB);  
}  
$('.selected').each(function(i, item) {  
  doSomething('a', 'b', function(retVal) {  
    // process retVal and item
  });
});

现在,如果回调是在.each()之外定义的,你必须按照你的方式来做,将item传递给doSomething():

function doSomething(varA, varB, self, callback) {  
  // do a lot of ajax stuff  
  callback(varA + varB, self);  
}  
function doSomethingCallback(retVal, self) {  
  // process retVal and item
}
$('.selected').each(function(i, item) {  
  doSomething('a', 'b', item, doSomethingCallback);
});