将参数传递给回调函数时,与回调函数的调用者发生冲突

What to do when passing a parameter into a callback function conflicts with the callback's caller

本文关键字:函数 回调 调用者 冲突 参数传递      更新时间:2023-09-26

我使用ID3阅读器脚本从音频文件检索数据。基本用法是:

ID3.loadTags(file,function()
{
  var attr = ID3.getAllTags(file).attribute;
});

,其中匿名函数是回调函数。这只是为了提供上下文,但是,我完全不确定我遇到的问题是特定于特定脚本的。

通常,在回调函数中,你可以提取你需要的信息,然后使用DOM设置元素的innerHTML属性,使其等于你提取的信息。

有时候你要提取一堆信息并将它们连接在一个长字符串中,我试图将它划分得更清楚一些,这样我的调用函数就会更清晰一些。我想做的是:

function callingFunction()
{
  var file = "whatever.mp3";
  var info = getInfo(file);
}
function calledFunction(file)
{
  var info = {data: 0};
  ID3.loadTags(file, function(passedVar)
  {
    var dataobj = ID3.getAllTags(file);
    passedVar.data = dataobj.title+etc+dataobj.album+....(it can get long);
  }(info));
  return info;
}

创建带有属性的对象是因为它是JS中模拟引用传递的唯一方法之一-将对象传递给回调函数,将适当的数据分配给对象中的属性,然后在calledFunction结束时,将对象返回给callingFunction。

它不起作用。现在,在上面的代码中,如果我说passsedvar。Data = "teststring"而不是从dataobj中分配数据,这样可以工作,因此将对象传递到回调函数是正确的。但是,如果对象是从ID3函数返回的数据对象中分配数据,则无法工作。它返回未定义,而且,Chrome的JS调试器说,ID3函数返回的对象是空的。当我这样做时,这进一步证实了:

function calledFunction(file)
{
  var info = {data: 0};
  ID3.loadTags(file, function(passedVar)
  {
    alert(ID3.getAllTags(file).(any attribute));
  }(info));
  return info;
}

,根本不会出现警告框。但是,如果去掉上面代码中传递给回调函数的参数,并保持其他所有内容不变,那么警告框就会像它应该的那样出现。

所以,总而言之,当我向回调函数传递一个参数时,由于某种原因,调用该回调函数的对象的另一个函数停止正常工作。

是否有可能将参数传递给回调函数以某种方式与ID3冲突或重写?loadTags函数正在传入回调函数,这就是为什么getAllTags函数失败?因为由于某种原因,当将参数传递给回调函数时,getAllTags函数不再获得正常运行所需的所有信息?这是我能想到的唯一解释。

如果是这种情况,有没有办法解决它?如果不是这样,那到底是怎么回事?

我想出了一个解决方案,但我觉得它很粗糙。我基本上创建了第三个函数,该函数从回调函数(它本身不接收任何参数)调用,该函数将getAllTags方法返回的对象作为参数,从该对象提取数据,并将其分配给其他函数可以访问的全局变量。所以,这:

var globalVar;
function calledFunction(file)
{
  //var info = {data: 0};
  ID3.loadTags(file, function()
  {
    thirdFunction(ID3.getAllTags(file));
  });
  //return info;
}
function thirdFunction(dataobj)
{
  globalVar = dataobj.title+etc;
}

但我真的不喜欢这个解决方案,我觉得它违背了我一开始所追求的划分精神。

不工作的原因:

function calledFunction(file)
{
  var info = {data: 0};
  ID3.loadTags(file, function(passedVar)
  {
    var dataobj = ID3.getAllTags(file);
    passedVar.data = dataobj.title+etc+dataobj.album+....(it can get long);
  }  (info));
  // ^^^^^^ --- calls the function immediately
  return info;
}

…是你的调用你的匿名函数,并传递该调用的结果(undefined)到ID3.loadTags。你不再向它传递一个函数了。

但是根本的问题是,你试图在loadTags调用它的回调之前使用数据对象,并把数据放在对象上。

我建议,因为它的输出依赖于异步操作,而不是依赖于函数返回值,所以您可以将calledFunction更改为接受回调函数。它应该是这样的:

function callingFunction() {
  getInfo('whatever.mp3', function(info) { // pass a callback function
    // info.data is here now
  });
}
function getInfo(file, cb) { // accept a callback function as the 2nd param
  ID3.loadTags(file, function() {
    var tags = ID3.getAllTags(file);
    // once your async operation is done, call cb and pass back the return value
    cb({
      data: tags.title+etc+tags.album+....(it can get long);
    });
  });
}

这种方法避免了您试图通过使用可以通过引用传递的对象来解决的问题,并且它确保您只有在异步操作(ID3.getAllTags)完成后才能继续。