2014-02-11 42 views
1

我有一個對象,它有一個loadFile()方法來分析一個wav文件。我一直在對象之外使用FileReader,並從讀取的文件中傳遞loadFile(),ArrayBuffer並讓它從那裏接管。我想要有可能的很多對象,所以我想在loadFile()方法中打包FileReader,所以我不必爲每個對象處理外部的所有閱讀器代碼。問題是,我不知道這將如何工作。這裏有一個可視代碼:在對象內部使用FileReader

function MyObject() { 
    this.property; 
    this.anotherProp; 
    this.data = new Array(); // array to be filled with PCM data for processing 
} 

// pass a File object 
MyObject.prototype.loadFile = function(file) { 
    var reader = new FileReader(); 
    reader.readAsArrayBuffer(file); 

    reader.onload = function(event) { 

     var buffer = event.target.result; 

     // do lots of stuff with buffer and eventually fill up this.data[] 

    } 

} 

MyObject.prototype.doProcessing = function() { 

    // process this.data[] 

} 

var file; // a File object I grabbed from somewhere 

var myObj = new MyObject(); 

myObj.loadFile(file); 

myObj.doProcessing(); 

loadFile()會發生什麼情況?在我有myObj.data[]的任何數據之前,loadFile會返回嗎?還是等待reader.onload才能退火?如果這是錯誤的做法,我該怎麼做? Aslo,如果我想loadFile()返回false如果內部reader.onload失敗?

可能的解決方案:http://jsfiddle.net/N6vnU/2/

目前的解決方案:我結束了移動文件的解析函數出對象的成網的工作人員,發現FileReaderSync。現在,我將文件發送給網絡工作人員,並在返回後創建一個包含結果的對象。

+1

add'var self = this;'在讀取器的onload()函數之上,self.data = onload()中的緩衝區,然後在reader.onload()的末尾調用self.doProcessing(),你就是金... – dandavis

+0

謝謝,這部分是led我到我目前的解決方案 –

回答

0

Javascript中的事件是異步的,因此您必須假設loadFile將在onload運行之前返回(始終假設爲最糟糕的情況,因爲您無法預測何時會完成異步調用)。

您通常的選擇是向loadFile添加回調參數,一旦onload完成,您將調用回調參數,或者選擇整合延期/期貨(如果您喜歡這種工作方式)。

另外一個暗示:你需要調用readAsArrayBuffer後你分配onload處理程序,因爲又因爲它是異步總有那麼你會錯過這個事件,如果你第一次指示瀏覽器讀取該文件,然後有機會附加一個事件。

+0

我試着給我的對象添加一個onload方法。它似乎在工作。讓我知道如果你看到它的一個潛在的問題:http://jsfiddle.net/N6vnU/ –

+0

以及你通常將回調函數作爲參數傳遞,而不是硬編碼它們以增加靈活性。例如你的小提琴的這個修改過的版本:http://jsfiddle.net/N6vnU/3或使用承諾的jQuery定義http://jsfiddle.net/N6vnU/4 - 處理錯誤狀態在兩者上都非常簡單,帶有承諾的解決方案是單線程http://jsfiddle.net/N6vnU/5/,然後您需要將自己附加到諾言上的'.fail'接口。 – gonchuki

0

是的,loadfile將在文件實際加載之前返回。 一個很好的方法可能涉及使用承諾。

例如,您可以使用Q庫。 以下是API的鏈接:https://github.com/kriskowal/q/wiki/API-Reference

如果您已經使用jQuery,$ .Deferred對象就足夠了,即使我建議您使用Q庫提供的承諾。

MyObject構造函數可以定義一個延遲(私有將是理想的),由reader.onload函數解決。

對MyObject實例的真正使用知之甚少,請考慮將以下內容讀爲僞代碼。

function MyObject() { 
    this.def = $.Deferred(); //the deferred to be resolved when the content has been loaded 
    this.property; 
    this.anotherProp; 
    this.data = new Array(); // array to be filled with PCM data for processing 
} 

// pass a File object 
MyObject.prototype.loadFile = function(file) { 
    var obj = this, 
     reader = new FileReader(); 
    this.def = $.Deferred(); 
    reader.readAsArrayBuffer(file); 

    reader.onload = function(event) { 
     var buffer = event.target.result; 
     obj.def.resolve(); 
     // do lots of stuff with buffer and eventually fill up this.data[] 
    } 

} 

MyObject.prototype.doProcessing = function() { 
    this.def.done(function(){ 
     // process this.data[] 
     console.log('resolved'); 
    }); 
} 

var file; // a File object I grabbed from somewhere 
var x = new MyObject(); 
x.loadFile(file); 
x.doProcessing(); //this would print 'resolved' when the file is loaded 
+0

我試着給我的對象添加一個onload方法,這似乎正在工作:http://jsfiddle.net/N6vnU/ –

+0

是的,Robby,這是一個很好的面向事件的工作解決方案。在這樣的情況下,解決方案是合理且易於理解的。 如果期望的行爲變得太複雜了,我建議你考慮使用承諾,因爲它們是一個強大的事件抽象。 –

+0

太棒了,如果事情變得像你說的那樣複雜,我一定會簽出承諾。我感謝您的意見! –