更新:完全解决方案在答案结束。如何使api调用一个而不是并发
有了这样的代码:
@Injectable()
export class FileUploader {
constructor(private http: Http) {}
upload(url: string, file: File) {
let fileReader: FileReader = new FileReader();
return new Promise((resolve, reject) => {
fileReader.onloadend = (e) => {
// you can perform an action with read data here
let content = fileReader.result;
console.log('starting upload');
return this.http.post(url, content)
.map((res) => res.json()).toPromise();
};
fileReader.readAsArrayBuffer(file);
});
}
和使用像
this.fileuploader.upload('/backend/upload', content).then(); // do something
但是,当用户选择多个文件(就像FB创作专辑),所有的文件将在上传同时完全阻止浏览器。
我的计划是在一些属性中放置promise数组,另一个私有方法会触发第一个属性;完成后,承诺会再次调用该方法,以便新的上传开始,直到全部完成。
我试过的所有组合都失败了,我甚至没有编译它们。即使上面的代码不是我的,但从其他问题中挑选出来。
如何做到这一点?
编辑:基于@toskv答案,这是我现在使用的解决方案。我更新了答案,以防其他人遇到同样的问题。
再次感谢@toskv的帮助。
@Injectable()
export class FileUploader {
private currentTask: Promise<any> = null;
constructor(private http: Http) {}
upload(url: string, file: File) {
let action =() => {
return new Promise((resolve) => {
let fileReader: FileReader = new FileReader();
fileReader.onloadend = (e) => {
let content = fileReader.result;
return this.http.post(url, content)
.map((res) => res.json()).toPromise()
.then((json) => {
resolve(json);
});
};
fileReader.readAsArrayBuffer(file);
})
};
return this.doNext(action)
}
private doNext(action:() => Promise<any>): Promise<any> {
if (this.currentTask) {
// if something is in progress do it after it is done
this.currentTask = this.currentTask.then(action);
} else {
// if this is the only action do it now
this.currentTask = action();
}
return this.currentTask;
}
}
我想'this.http'是角HTTP服务,它是利用观测量。如果是这样,你可以使用'mergeMap'或'concatMap'来实现所需的行为:https://www.learnrxjs.io/operators/transformation/concatmap.html –