2014-02-11 20 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

太棒了,如果事情变得像你说的那样复杂,我一定会签出承诺。我感谢您的意见! –