[英]How to use observable without await
我有以下代碼,這似乎有效,但我很確定有一種更簡潔的方法可以使用鏈接運算符來實現它,事實是我在上面掙扎了 2 個小時,但無法使其正常工作用另一種方式。
也許你可以幫助我?
public synchronizeWithRemote$(state: Partial<StorageCustomerCase>, pdfDocument?: InkPDFDocument): Observable<ISynchronizationProgress> {
return new Observable((subscriber) => {
// PDF as changed, we update the hash
if (pdfDocument) {
this.pdfInvalidationHash = nanoid();
// Start synchronization task
pdfDocument
.serialize()
.then((serializedDoc) => {
const task = this.storageRef.put(serializedDoc, { contentType: "application/pdf" });
// Listen for changes
task.on("state_changed", ({ bytesTransferred, totalBytes }) => {
subscriber.next({ bytesTransferred, totalBytes, percent: Math.round((bytesTransferred * 100) / totalBytes) });
});
return task; // Await the load to finish before uploading to firestore the metadatas
})
.then(() =>
this.documentRef.update({ ...omit(state, "id"), pdf_invalidation_hash: this.pdfInvalidationHash } as StorageCustomerCase),
)
.then(() => subscriber.complete());
} else {
subscriber.next({ bytesTransferred: 0, percent: 100, totalBytes: 0 });
// TODO: Update this function to use only observable by chaining
// Just update doc
this.documentRef
.update({ ...omit(state, "id"), pdf_invalidation_hash: this.pdfInvalidationHash } as StorageCustomerCase)
.then(() => {
// Notify firebase of changes, once PDF has been successfully uploaded.
subscriber.complete();
});
}
});
}
如果有PDF文檔,它應該發送一個進度指示器,並在上傳后與firestore同步,否則,它僅在與firestore同步后完成。
問候, 安德烈亞斯
這應該與使用 Promise 的語義大致相同,僅使用 Observables。 出於顯而易見的原因,我實際上無法為您進行測試,因此請將其用作答案的草圖而不是整個答案。
我也不確定fromEventPattern
適用於您的情況。 看起來應該如此。
public synchronizeWithRemote$(state: Partial<StorageCustomerCase>, pdfDocument?: InkPDFDocument): Observable<ISynchronizationProgress> {
const finish$ = defer(() => this.documentRef.update({
...omit(state, "id"),
pdf_invalidation_hash: this.pdfInvalidationHash
} as StorageCustomerCase));
if(doc == null){
// No updates, finish right away
return finish$.pipe(
startWith({ bytesTransferred: 0, percent: 100, totalBytes: 0 })
);
}
// Stream of state Changes
const update$ = defer(() => doc.serialize()).pipe(
tap(_ => this.pdfInvalidationHash = nanoid()),
map(serializedDoc =>
this.storageRef.put(serializedDoc, {
contentType: "application/pdf"
})
),
switchMap(task =>
fromEventPattern(
handler => task.on("state_changed", handler)
).pipe(
map(({ bytesTransferred, totalBytes }) => ({
bytesTransferred,
totalBytes,
percent: Math.round((bytesTransferred * 100) / totalBytes)
}))
)
)
);
// Wait for update$ to complete before subscribing to finish$
return concat(update$, finish$);
}
許多 RxJS 操作符,如果給定一個 promise,就會隱式地將它們轉換為 obervable。 以下是一些:
from(promise)
defer(() => promise)
mergeMap/switchMap/concatMap(val => promise)
我不是#1 的忠實粉絲。 雖然#2 和#3 保持承諾的行為就像一個可觀察的(在您訂閱之前什么都不會發生),#1 將立即啟動承諾。 任何事情都有時間和地點,但是使用 #1 產生的錯誤在這里很常見,所以我認為值得一提。
一個很好的例子; 如果我在這里使用 #1 而不是 #2 作為完成 $,那么pdf_invalidation_hash
將具有錯誤的值。 因為它的值取決於訂閱完成 $ 的時間(在update$
運行后,應該更新this.pdfInvalidationHash
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.