gpt4 book ai didi

javascript - 链接管道操作后如何从 Angular 服务中返回可观察值

转载 作者:行者123 更新时间:2023-12-02 23:04:17 25 4
gpt4 key购买 nike

我正在尝试链接/管道操作并从使用 Angular Fire 的 Angular 服务返回 Observable。

有了 promise ,我就能做到这一点

服务

saveDiploma(diploma: { title: any; description: any; picture: any }) {
return new Observable(observer => {
const id = this.db.createId();
this.storage.ref(`diplomas/${id}/original.jpg`)
.putString(diploma.picture, 'data_url')
.then(task => {
task.ref.getDownloadURL()
.then(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'
};
this.db.doc(`diplomas/${id}`)
.set(saved)
.then(() => {
observer.next(saved);
observer.complete();
})
.catch(e => observer.error(e));
})
.catch(e => observer.error(e));
})
.catch(e => observer.error(e));
});
}

组件

save() {
this.diplomasService.saveDiploma({
title: this.diplomaForm.value.title,
description: this.diplomaForm.value.description,
picture: this.currentImage
}).subscribe(diploma => {
console.log('saved diploma', diploma);
}, e => console.error('error while saving the diploma', e));
}

我正在尝试在服务中使用 Observables 而不是 Promise 并通过管道传输它们 in order像这样

saveDiploma(diploma: { title: any; description: any; picture: any }) {
const id = this.db.createId();
const ref = this.storage.ref(`diplomas/${id}/original.jpg`);
return ref.putString(diploma.picture, 'data_url').snapshotChanges().pipe(
concatMap(task => {
console.log('getDownloadURL');
return from(task.ref.getDownloadURL());
}),
concatMap(url => {
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));
})
);
}

但是 getDownloadURL 方法在上传完成之前被触发,因此返回错误storage/object-not-found。我尝试在 concatMap(getDownloadURL) 之前添加终结或过滤器(在 task.state == 'success' 上),但未能使其正常工作。

有谁知道如何通过管道传输此操作并从中返回可观察对象?

我正在使用 Angular 8.1.2、Angular Fire 5.2.1 和 rxjs 6.5.1

最佳答案

根据 AngularFire 文档ref.putString(..).snapshotChanges()

Emits the raw UploadTaskSnapshot as the file upload progresses.

所以你的问题是 .snapshotChanges() 在文件上传完成之前发出。 concatMap 会在每次从源发出时触发,而不仅仅是在完成时触发。您应该使用concat

saveDiploma(diploma: { title: any; description: any; picture: any }) {
const id = this.db.createId();
const ref = this.storage.ref(`diplomas/${id}/original.jpg`);
return concat(
ref.putString(diploma.picture, 'data_url').snapshotChanges().pipe(ignoreElements()),
defer(() => ref.getDownloadURL().pipe(
switchMap(url => {
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 this.db.doc(`diplomas/${id}`).set(saved); // you can return a Promise directly
})
))
);
}

可能的替代方案:

saveDiploma(diploma: { title: any; description: any; picture: any }) {
const id = this.db.createId();
const ref = this.storage.ref(`diplomas/${id}/original.jpg`);
return ref.putString(diploma.picture, 'data_url').snapshotChanges().pipe(
last(),
switchMap(() => ref.getDownloadURL()),
map(url => ({
title: diploma.title,
description: diploma.description,
url,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
createdBy: this.auth.auth.currentUser ? this.auth.auth.currentUser.uid : 'anonymous'
})),
switchMap(saved => this.db.doc(`diplomas/${id}`).set(saved))
);
}

关于javascript - 链接管道操作后如何从 Angular 服务中返回可观察值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57660293/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com