Javascript 在对象内部使用FileReader
我有一个对象,它有一个解析wav文件的Javascript 在对象内部使用FileReader,javascript,filereader,Javascript,Filereader,我有一个对象,它有一个解析wav文件的loadFile()方法。我一直在对象外部使用FileReader,并将loadFile()从读取的文件中传递ArrayBuffer,让它从那里接管。我希望可能有许多对象,因此我希望在loadFile()方法中封装一个FileReader,这样我就不必为每个对象处理外部的所有读卡器代码。问题是,我不确定这将如何运作。下面是一个可视代码: function MyObject() { this.property; this.anotherProp
loadFile()
方法。我一直在对象外部使用FileReader
,并将loadFile()
从读取的文件中传递ArrayBuffer
,让它从那里接管。我希望可能有许多对象,因此我希望在loadFile()
方法中封装一个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
启动吗?如果这样做是错误的,我应该怎么做?同样,如果loadFile()
中的reader.onload
失败,我希望loadFile()返回false
该怎么办
可能的解决方案:
当前解决方案:我最终将文件解析功能从对象移到了web worker中,并发现了FileReaderSync
。现在,我将文件发送给web worker,并在返回结果后创建一个对象。Javascript中的事件是异步的,因此您必须假设loadFile
将在onload
运行之前返回(总是假设在最坏的情况下,因为您无法预测异步调用何时完成)
您通常的选择是在loadFile
中添加一个回调参数,一旦onload
完成,您将调用该参数,或者如果您希望这样做,可以选择集成延迟/未来
还有一个提示:在分配onload
处理程序后,需要调用readAsArrayBuffer
,因为它是异步的,如果您首先指示浏览器读取文件,然后将事件附加到该文件上,则始终有可能错过此事件。是,loadfile将在文件实际加载之前返回。
一个好的方法可能包括使用承诺
例如,您可以使用Q库。
以下是API的链接:
如果您已经使用jQuery,那么$.Deferred对象就足够了,尽管我建议您使用Q库提供的承诺
MyObject构造函数可以定义一个延迟的(最好是私有的)函数,由reader.onload
函数解析
对MyObjor实例的实际使用知之甚少,请将下面的内容视为伪代码。
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
添加'var self=this;'在reader onload()函数上方,在onload()中使用self.data=buffer,然后在reader.onload()的末尾调用self.doProcessing(),您真是棒极了……谢谢,这部分地让我找到了我当前的解决方案。我试着在我的对象中添加一个onload方法,该方法似乎正在工作:是的,Robby,这是一个很好的面向事件的工作解决方案。在这种情况下,解决方案是合理且易于理解的。如果期望的行为变得过于复杂,我建议你考虑使用承诺,因为它们是一个强有力的事件抽象。令人敬畏的,我肯定会检查出承诺,如果事情变得复杂如你所说。我感谢你的意见!只是一个机警的乔瓦尼,这是对承诺的一种不好的使用。实际上,您希望返回loadFile函数的承诺,并在外部处理返回值的操作,最终得到以下用例:x.loadFile(file)。然后(x.doProcessing)
。否则,这个代码示例并不比使用回调更好,实际上更复杂。它似乎起作用了。如果您看到它的潜在问题,请告诉我:通常您会将回调函数作为参数传递,而不是硬编码它们以增加灵活性。例如,fiddle的这个修改版本:或者使用jQuery对承诺的定义——处理错误状态在这两个方面都非常简单,带有承诺的解决方案是一行,然后您需要将自己附加到承诺上的.fail
接口。