Кач*_*фей 5 rxjs typescript angular
我有两个服务。
1) UploadService- 将文件通过 ajax 发送到服务器,并获取并存储进度值(在 xhr.upload.onprogress 事件处理程序中)
2)SomeOtherService使用 DOM,从第一个服务获取进度值,将其显示在 Bootstrap 进度条上。
因为,xhr.upload.onprogress是异步的 - 我Observable在第一个服务中使用:
constructor () {
this.progress$ = new Observable(observer => {
this.progressObserver = observer
}).share();
}
private makeFileRequest (url: string, params: string[], files: File[]): Promise<any> {
return new Promise((resolve, reject) => {
let formData: FormData = new FormData(),
xhr: XMLHttpRequest = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) {
formData.append("uploads[]", files[i], files[i].name);
}
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject(xhr.response);
}
}
};
xhr.upload.onprogress = (event) => {
this.progress = Math.round(event.loaded / event.total * 100);
this.progressObserver.next(this.progress);
};
xhr.open('POST', url, true);
xhr.send(formData);
});
}
Run Code Online (Sandbox Code Playgroud)
Insise 第二个服务,我订阅了这个观察者:
this.fileUploadService.progress$.subscribe(progress => {
this.uploadProgress = progress
});
this.fileUploadService.upload('/api/upload-file', [], this.file);
Run Code Online (Sandbox Code Playgroud)
现在我的问题:
该代码不起作用。在第二次服务中,我仅获得一次观察值,100%。
但是如果我插入(是的,带有空的回调主体)
setInterval(() => {
}, 500);
Run Code Online (Sandbox Code Playgroud)
在 makeFileRequest 方法中 - 我将每 500 毫秒在第二个服务中获取进度值。
private makeFileRequest (url: string, params: string[], files: File[]): Promise<any> {
return new Promise((resolve, reject) => {
let formData: FormData = new FormData(),
xhr: XMLHttpRequest = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) {
formData.append("uploads[]", files[i], files[i].name);
}
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject(xhr.response);
}
}
};
setInterval(() => {
}, 500);
xhr.upload.onprogress = (event) => {
this.progress = Math.round(event.loaded / event.total * 100);
this.progressObserver.next(this.progress);
};
xhr.open('POST', url, true);
xhr.send(formData);
});
}
Run Code Online (Sandbox Code Playgroud)
那是什么?为什么会这样?我如何在onprogress没有 setInterval 的情况下正确使用 Observable 和事件?
UPD:在 Thierry Templier 里面回答之后
this.service.progress$.subscribe( data => {
console.log('progress = '+data);
});
Run Code Online (Sandbox Code Playgroud)
我得到了正确的值,但该值没有在模板内动态更新,仅再次 100%。
我没有完整的代码,所以很难给你一个准确的答案。
事实上,你说“在第二次服务中,我只获得一次观察值,100%”。让我觉得应该和promise的使用有关。事实上,Promise 可以一次性解决或拒绝。不支持与可观察量相反的多个事件。
如果您可以将代码与 plunkr 一起发布,我将能够对其进行调试,以便为您提供更准确的答案。
编辑
我创建了一个plunkr(http://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=preview)来测试您的代码,看起来它可以工作。通过将承诺更改为可观察的,我可以获得更多进度提示。
makeFileRequest(url: string, params: string[], files: File[]): Observable> {
return Observable.create(observer => {
let formData: FormData = new FormData(),
xhr: XMLHttpRequest = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) {
formData.append("uploads[]", files[i], files[i].name);
}
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
observer.next(JSON.parse(xhr.response));
observer.complete();
} else {
observer.error(xhr.response);
}
}
};
xhr.upload.onprogress = (event) => {
this.progress = Math.round(event.loaded / event.total * 100);
this.progressObserver.next(this.progress);
};
xhr.open('POST', url, true);
xhr.send(formData);
});
}
Run Code Online (Sandbox Code Playgroud)
这是我的痕迹:
app.component.ts:18 progress = 21
app.component.ts:18 progress = 44
app.component.ts:18 progress = 71
app.component.ts:18 progress = 100
Run Code Online (Sandbox Code Playgroud)
有了承诺,我只得到两条痕迹
| 归档时间: |
|
| 查看次数: |
4105 次 |
| 最近记录: |