1

我正在使用 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 中模拟引用传递的唯一方法之一——将对象传递给回调函数,将适当的数据分配给对象中的属性,然后在调用函数结束时,返回调用函数的对象。

但它不起作用。现在,在上面的代码中,如果我说 passVar.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 函数不再获取它正常运行所需的所有信息?这是我能想到的唯一解释。

如果是这种情况,有没有办法解决它?如果这不是正在发生的事情,那是怎么回事?

我想出了一个解决方案,但我觉得它很hacky。我基本上创建了从回调函数调用的第三个函数(它本身不接收参数),它将 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;
}

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

我会很感激任何帮助。

4

1 回答 1

1

这不起作用的原因:

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) 完成后才能继续。

于 2013-06-13T07:13:50.163 回答