如何让FileReader的onload函数优先执行后再处理后续API请求逻辑
问题解决:确保FileReader onload完成后再执行后续操作
我想要读取上传的文件并通过服务API发送文件内容,但目前onload函数最后执行。我需要让onload函数先执行完成,再进行后续步骤。
原代码如下:
checkInScript(file: File, scriptName: string): Observable<Response>{ console.log("****Before Calling Method***"); this.checkValidFile(file).then((value) => { console.log("****value****",value); this.fileValue.next(value); }) console.log("****After Calling method***"); const formData = new FormData(); formData.append('updateScript', this.fileValue.value); console.log("****Form Data***"); return this.http.post(this.mccScriptOperationURL + '/updateScript/' + scriptName, formData); } checkValidFile(file: File): Promise<string>{ const fileReader = new FileReader(); fileReader.readAsText(file); return new Promise((resolve) => { fileReader.onload = () => { console.log("****Inside on Load*****"); resolve(fileReader.result.toString()); }; }); }
当前执行顺序:
****Before Calling Method*** ****After Calling method*** ****Form Data*** ****Inside on Load***** ****value****
期望执行顺序:
****Before Calling Method*** ****Inside on Load***** ****value**** ****After Calling method*** ****Form Data***
解决方法
问题根源在于checkValidFile返回的是Promise(异步操作),原代码中没有等待它完成就执行了后续逻辑,导致顺序混乱。以下两种方案都能解决:
方案1:使用async/await(简洁直观)
将checkInScript改为异步函数,等待文件读取完成后再执行后续步骤:
async checkInScript(file: File, scriptName: string): Observable<Response> { console.log("****Before Calling Method***"); // 等待checkValidFile完成,拿到文件内容 const value = await this.checkValidFile(file); console.log("****value****", value); this.fileValue.next(value); console.log("****After Calling method***"); const formData = new FormData(); // 直接用拿到的value,无需依赖fileValue formData.append('updateScript', value); console.log("****Form Data***"); return this.http.post(this.mccScriptOperationURL + '/updateScript/' + scriptName, formData); } checkValidFile(file: File): Promise<string> { const fileReader = new FileReader(); fileReader.readAsText(file); return new Promise((resolve) => { fileReader.onload = () => { console.log("****Inside on Load*****"); resolve(fileReader.result.toString()); }; }); }
方案2:用RxJS转换Promise并串联逻辑
如果更倾向于RxJS风格,可以把Promise转成Observable,用switchMap串联后续操作:
import { from } from 'rxjs'; import { switchMap } from 'rxjs/operators'; checkInScript(file: File, scriptName: string): Observable<Response> { console.log("****Before Calling Method***"); // 将Promise转为Observable,等待完成后执行后续逻辑 return from(this.checkValidFile(file)).pipe( switchMap(value => { console.log("****value****", value); this.fileValue.next(value); console.log("****After Calling method***"); const formData = new FormData(); formData.append('updateScript', value); console.log("****Form Data***"); return this.http.post(this.mccScriptOperationURL + '/updateScript/' + scriptName, formData); }) ); } checkValidFile(file: File): Promise<string> { const fileReader = new FileReader(); fileReader.readAsText(file); return new Promise((resolve) => { fileReader.onload = () => { console.log("****Inside on Load*****"); resolve(fileReader.result.toString()); }; }); }
说明
两种方案都能保证onload完成后再执行创建FormData和API请求的逻辑,符合你期望的执行顺序。其中async/await更贴近同步代码的写法,RxJS方案则更适配Angular的Observable生态。
内容的提问来源于stack exchange,提问作者sharath
相关产品推荐
相关产品推荐

