Javascript 如何在链接管道操作后以角度返回服务中的可观测值
我正在尝试链式/管道式操作,并从angular中使用angular fire的服务返回一个可观察的对象 有了承诺,我就有了工作 服务 保存文凭(文凭:{头衔:任意;描述:任意;图片:任意}){ 返回新的可观察对象(观察者=>{ const id=this.db.createId(); this.storage.ref(`policials/${id}/original.jpg`) .putString(文凭.图片,“数据\ url”) .然后(任务=>{ task.ref.getDownloadURL() 。然后(url=>{ 已保存常数={ 头衔:文凭, 描述:文凭, 网址, createdAt:firebase.firestore.FieldValue.serverTimestamp(), createdBy:this.auth.auth.currentUser?this.auth.auth.currentUser.uid:“匿名” }; this.db.doc(`emplicas/${id}`) .set(已保存) .然后(()=>{ 下一步(已保存); observer.complete(); }) .catch(e=>observer.error(e)); }) .catch(e=>observer.error(e)); }) .catch(e=>observer.error(e)); }); } 组成部分Javascript 如何在链接管道操作后以角度返回服务中的可观测值,javascript,angular,rxjs,angularfire2,Javascript,Angular,Rxjs,Angularfire2,我正在尝试链式/管道式操作,并从angular中使用angular fire的服务返回一个可观察的对象 有了承诺,我就有了工作 服务 保存文凭(文凭:{头衔:任意;描述:任意;图片:任意}){ 返回新的可观察对象(观察者=>{ const id=this.db.createId(); this.storage.ref(`policials/${id}/original.jpg`) .putString(文凭.图片,“数据\ url”) .然后(任务=>{ task.ref.getDownload
save(){
这是我的文凭服务({
标题:this.emplicalform.value.title,
description:this.form.value.description,
图片:此为当前图片
}).订阅(文凭=>{
console.log(“保存的文凭”,文凭);
},e=>console.error('保存文凭时出错',e));
}
我试图在服务中使用可观察到的东西,而不是承诺,并像这样使用它们
保存文凭(文凭:{头衔:任意;描述:任意;图片:任意}){
const id=this.db.createId();
const ref=this.storage.ref(`emplicas/${id}/original.jpg`);
返回ref.putString(diplication.picture,'data_url').snapshotChanges().pipe(
concatMap(任务=>{
log('getDownloadURL');
从(task.ref.getDownloadURL())返回;
}),
concatMap(url=>{
log('url',url);
已保存常数={
头衔:文凭,
描述:文凭,
网址,
createdAt:firebase.firestore.FieldValue.serverTimestamp(),
createdBy:this.auth.auth.currentUser?this.auth.auth.currentUser.uid:“匿名”
};
从(this.db.doc(`emplicas/${id}`).set(saved))返回;
})
);
}
但是getDownloadURL方法在上传完成之前被触发,因此返回一个错误存储/objectnotfound
。我尝试在concatMap(getDownloadURL)之前添加一个finalize或filter(on task.state=='success'),但未能使其正常工作
有人知道如何通过管道进行这些操作并从中返回一个可观察到的结果吗
我使用的是Angular 8.1.2、Angular Fire 5.2.1和rxjs 6.5.1,这里的问题是,默认情况下,承诺是急切的。我认为将
from
操作符与defer
操作符()包装应该可以解决您的问题。所以代码看起来像这样:
return ref.putString(diploma.picture, 'data_url').snapshotChanges().pipe(
concatMap(task => defer(() => {
console.log('getDownloadURL');
return from(task.ref.getDownloadURL());
})),
concatMap(url => defer(() => {
console.log('url', url);
const saved = {
title: diploma.title,
description: diploma.description,
url,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
createdBy: this.auth.auth.currentUser ? this.auth.auth.currentUser.uid : 'anonymous'
};
return from(this.db.doc(`diplomas/${id}`).set(saved));
}))
一旦订阅了传递给defer的方法,就会对其进行评估。一旦有来自源可观测对象的传入通知,ConcatMap将自动订阅内部可观测对象。根据AngularFire文档
ref.putString(..).snapshotChanges()
在文件上载过程中发出原始上载任务快照
因此,您的问题是,.snapshotChanges()
在文件上载完成之前发出concatMap
在源的每次发射时触发,而不仅仅是在完成时触发。您应该使用concat
保存文凭(文凭:{头衔:任意;描述:任意;图片:任意}){
const id=this.db.createId();
const ref=this.storage.ref(`emplicas/${id}/original.jpg`);
返回海螺(
ref.putString(diplificate.picture,'data_url').snapshotChanges().pipe(ignoreElements()),
延迟(()=>ref.getDownloadURL()管道(
开关映射(url=>{
log('url',url);
已保存常数={
头衔:文凭,
描述:文凭,
网址,
createdAt:firebase.firestore.FieldValue.serverTimestamp(),
createdBy:this.auth.auth.currentUser?this.auth.auth.currentUser.uid:“匿名”
};
返回此.db.doc(`complicals/${id}`).set(已保存);//您可以直接返回承诺
})
))
);
}
可能的替代方案:
保存文凭(文凭:{头衔:任意;描述:任意;图片:任意}){
const id=this.db.createId();
const ref=this.storage.ref(`emplicas/${id}/original.jpg`);
返回ref.putString(diplication.picture,'data_url').snapshotChanges().pipe(
最后(),
switchMap(()=>ref.getDownloadURL()),
地图(url=>({
头衔:文凭,
描述:文凭,
网址,
createdAt:firebase.firestore.FieldValue.serverTimestamp(),
createdBy:this.auth.auth.currentUser?this.auth.auth.currentUser.uid:“匿名”
})),
switchMap(saved=>this.db.doc(`emplicas/${id}`).set(saved))
);
}
您的文件是否可能上载
next
s上载进度?在这种情况下,您可能不希望在值上显示concatMap()
,因为这是