更新:完全解決方案在答案結束。如何使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 –