【问题标题】:How to handle for promise inside a piped map如何在管道地图中处理承诺
【发布时间】:2019-05-08 00:36:47
【问题描述】:

我确信我在这里很困惑,所以请提供任何帮助。

这是我的场景:

我从 Firestore 中提取了一个文档:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      map( document => {

      })
    );

到这里一切都很好。

但在地图内部,我需要一个承诺来解决(或不解决)

例如:

return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      map( document => {
        // This is a promise the below part 
        const data = await EventImporterJSON.getFromJSON(document.payload.data())
        return data
      })
    );

我知道await 不可能在那里发生。我很困惑如何解决这个问题,也许我在 observables 和 rxjs 上工作的时间不够长。

最后我想要实现的是:

获取文档。映射并处理它,但在这个过程中,我需要处理一个承诺。

不过,我不想将这个承诺返回给调用者。

这有意义吗?

或者我的结构完全错误?

【问题讨论】:

    标签: javascript rxjs google-cloud-firestore observable


    【解决方案1】:

    这是mergeMapconcatMap 的典型用例:

    return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      mergeMap(document => {
        // This is a promise the below part 
        return EventImporterJSON.getFromJSON(document.payload.data())
      })
    );
    

    但是,您也可以使用 async - await,因为 mergeMap 等运算符以相同的方式处理 Observables、Promise、数组等,因此您只需在 mergeMaps 项目函数中返回一个 Promise 即可工作正常。

    通常,您不需要在单个方法中使用多个 awaits,因为更“Rx”的处理方式是链接运算符,但如果您愿意,您也可以这样做,因为 async 方法返回一个 Promise 和 RxJS将像处理任何其他 Promise 一样处理它。

    const delayedPromise = () => new Promise(resolve => {
      setTimeout(() => resolve(), 1000);
    })
    
    of('a').pipe(
      mergeMap(async v => {
        console.log(1);
        await delayedPromise();
        console.log(2);
        await delayedPromise();
        console.log(3);
        await delayedPromise();
        return v;
      })
    ).subscribe(console.log);
    // 1
    // 2
    // 3
    // a
    
    Live demo: https://stackblitz.com/edit/rxjs-3fujcs
    

    【讨论】:

    • 谢谢,马丁一如既往地给出了最全面的答案之一。我会将您的标记为已接受,但对 Kevins 的回答有何想法?
    【解决方案2】:

    Observables 可以看作是 Promise 的一层,你为什么不这样使用你的 Promise 呢? 像这样:

    let getDataFromJson(payloadData){
        return from(EventImporterJSON.getFromJSON(payloadData());
    }
    
    return this.afs.collection("events").doc(eventID).snapshotChanges().pipe(
      map(document=>document.payload.data),
      switchMap( payloadData=> getDataFromJson(payloadData)))
    .subscribe(result=>{
        //final result
    });
    

    1 用 map 管道你的第一个 observable 只是为了简化你的返回值

    2 switchMap 到另一个可观察对象,这将是您作为可观察对象的承诺(使用“来自”运算符);

    map 操作符是为了以同步和“纯粹”的方式改进结果,比如只返回对象的少数属性或过滤数据,在这里你想链接两个异步操作,所以我建议你将它保留在 rx 方法中

    【讨论】:

    • 我也喜欢凯文这个答案
    猜你喜欢
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2021-04-10
    • 2018-04-30
    • 2020-04-11
    • 1970-01-01
    相关资源
    最近更新 更多