Firebase 我如何强制一个可观察的对象完成?

Firebase 我如何强制一个可观察的对象完成?,firebase,rxjs,xstate,rxfire,Firebase,Rxjs,Xstate,Rxfire,这是一个利基问题,但我知道问题是什么,所以希望这里有人能帮助我。这是一个可观察/RXFire问题,而不是xstate问题 我有一台机器,它调用一个可观察的: export const tribeMachine = Machine( { id: "council", initial: "init", context: {}, states: { init: { invoke: { id: "gettribes",

这是一个利基问题,但我知道问题是什么,所以希望这里有人能帮助我。这是一个可观察/RXFire问题,而不是xstate问题

我有一台机器,它调用一个可观察的:

export const tribeMachine = Machine(
  {
    id: "council",
    initial: "init",
    context: {},
    states: {
      init: {
        invoke: {
          id: "gettribes",
          src: () =>
            collectionData(database.collection("tribes")).pipe(
              concatAll(),
              map(x => ({ type: "STORE", x }))
            ),
          onDone: "loaded"
        },
        on: {
          STORE: {
            actions: "storetribes"
          },
          CANCEL: "loaded"
        }
      },
      loaded: {
        entry: () => console.log("loaded")
      },
      error: {
        entry: () => console.log("error")
      }
    }
  },
  {
    actions: {
      storetribes: (context, event) => console.log("hello")
    }
  }
);
它的工作方式是,机器在加载时调用observable,然后一旦obs发出其值并调用complete(),调用invoke.onDone,机器将转换到“loaded”状态

当我使用通过complete()调用创建的普通可观察对象时,或者当我将take(#)添加到.pipe()的末尾时,转换工作正常

但由于某种原因,来自RXFire的collectionData()的可观测数据不会发出“完整”信号。。。机器就在那里

我已经尝试将一个空()添加到末端,并将()连接到观察对象,以便将完整的信号添加到管道末端。。。但后来我发现empty()已被弃用,而且它似乎无论如何都不起作用

我的头撞在墙上有一段时间了。感谢您的帮助


编辑:

解决方案:

我误解了收集数据的目的()。它是一个侦听器,所以它不应该完成。我把一个方形的钉子插在圆孔里。解决方案是重构xstate机器,因此我根本不需要调用OnOne

谢谢你的回答


EDIT2:让它开始工作了

take(1)可以在concatAll()之前调用。我想如果你先叫它,它会结束这条流,但事实并非如此。管道中的其他操作符仍然适用。因此,我使用(1)获取单个数组,使用concatAll()将数组展平为单个对象流,然后将该数据映射到触发存储操作的新对象。存储操作然后将数据设置为机器的上下文

export const tribeMachine = Machine({
    id: 'council',
    initial: 'init',
    context: {
        tribes: {},
        markers: []
    },
    states: {
        init: {
            invoke: {
                id: 'gettribes',
                src: () => collectionData(database.collection('tribes')).pipe(
                    take(1),
                    concatAll(),
                    map(value => ({ type: 'TRIBESTORE', value })),
                ),
                onDone: 'loaded'
            },
            on: {
                TRIBESTORE: {
                    actions: ['storetribes', 'logtribes']
                },
                CANCEL: 'loaded'
            }
        },
        loaded: {
        },
        error: {
        }
    }
},
    {
        actions: {
            storetribes: assign((context, event) => {
                return {
                    tribes: {
                        ...context.tribes,
                        [event.value.id]: event.value
                     },
                     markers: [
                         ...context.markers,
                         {
                             lat: event.value.lat,
                             lng: event.value.lng,
                             title: event.value.tribeName
                         }
                        ]
                     }
            })
        }
    }
)

谢谢大家的帮助

可观察对象可以随时间返回多个值,因此由
collectionData()
决定何时完成(即导致调用complete()

但是,如果您只想从可观察对象中获取1个值,您可以尝试:

  collectionData(database.collection("tribes")).pipe(
              take(1),
              concatAll(),
              map(x => ({ type: "STORE", x }))
            ),
这将导致从
collectionData()
中获取1个值后,observable完成


注意:这可能不是最好的解决方案,因为它取决于您使用的可观察流的工作方式。我只是强调一下,您可以使用
take(1)
只获取1个值并完成可观察的源代码。

文档collectionData()提取的数量是动态的。没有意识到可以在concatAll()之前调用take(1)!成功了。非常感谢。