2013-06-13 118 views
1

我正在使用ID3讀取器腳本從音頻文件中檢索數據。基本用法是:將參數傳遞到回調函數時與回調的調用方衝突

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

其中匿名函數是一個回調函數。這只是爲了提供上下文,但是,我並不確定我遇到的問題是特定於該特定腳本的。

通常,在回調函數內部,您可以提取所需的信息,然後使用DOM將any元素的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唯一的途徑之一 - 對象傳遞到回調函數,分配相應的數據對象中的屬性,然後在調用函數結束時,將對象返回給callingFunction。

它雖然不工作。現在,在上面的代碼中,如果我說的是傳遞VarData =「teststring」而不是從dataobj分配數據,那麼這將起作用,因此將對象傳遞到回調函數中是正常工作的。但是,如果從ID3函數返回的數據對象中爲對象分配數據,則不起作用。它返回undefined,而且,Chrome的JS調試器說ID3函數返回的對象爲null。這是進一步證實當我這樣做:

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; 
} 

但我真的不喜歡這個解決方案,我覺得它違背了條塊分割的精神,我是在這個首位之後。

我很感激任何幫助。

回答

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)完成。

+0

是的,我真的應該認爲它是異步的。還沒有我的咖啡! :-) –

+0

由於我的回答錯過了主要觀點,我刪除了它並冒昧將相關部分放入您的論文。 –

+0

是的,我曾認爲異步可能與它有關,但我也認爲,因爲有一個回調函數被傳遞到ID3函數,那不是它。如果我更徹底地調查了這個角度,我可以節省很多時間。感謝那個漂亮,優雅的解決方案。 :) – namkcuR