【问题标题】:Functions in epic are firing out of order and I can't understand why史诗中的功能出现故障,我不明白为什么
【发布时间】:2017-05-07 15:39:09
【问题描述】:

*已解决 问题在于我如何创建和响应由 firebase 回调创建的 observable。 我的 firebase 回调中也发生了太多事情。 最后,我使用 firebase 承诺结构将其进一步拆分:https://firebase.googleblog.com/2016/01/keeping-our-promises-and-callbacks_76.html 并在现在称为 firebaseAPI.checkForUser 中为 firebase 回调创建 Observable.fromPromise。 *

工作史诗:

export const contactFormFirebaseSubmitEpic = (action$) =>
action$.ofType(START_CONTACT_FORM_FIREBASE_SUBMIT)
  .flatMap((firebaseSubmitAction) => {
   const values = firebaseSubmitAction.values;
   const formattedEmail = firebaseAPI.getFormattedEmail(values);
   const contactsRef = firebaseAPI.getContactsRef(formattedEmail);
    return firebaseAPI.checkForUser(values, formattedEmail, contactsRef);
 })
  .flatMap((data) => concat(
        of(firebaseAPI.recordUserAndUpdateDetails(data))
      ))
  .flatMap((data) => concat(
     of(firebaseAPI.setQuoteData(data))
    ))
  .switchMap((x) => merge(
      of(stopLoading()),
      of(contactFormFirebaseSuccess())
    ));

// 原题

好的,我想要实现的是执行第一个操作(firebaseAPI.checkUserAndUpdate),然后执行下一个操作,然后当它们都完成后,基本上丢弃那里的内容并发送两个操作(contactFormFirebaseSuccess 和 stopLoading) .

这一切都很好,除了一件奇怪的事情,setQuoteData 函数总是在 checkUser 函数之前运行。有谁知道为什么会这样?

此外,如果有更好的方法来解决这个问题,我会非常愿意接受建议!干杯。此外,我还去掉了很多变量和一些会使它变得更加复杂的东西。基本上,我只是想表明,在每种情况下,我都会从“用 firebase 做某事”中返回一个可观察的。但我不认为这是问题所在,因为我在每个 firebase 函数中都有控制台日志,而 setQuoteData 只是先触发,然后执行 firebase 内容,然后在完成后运行 checkUserAndUpdate 。

export const contactFormFirebaseSubmitEpic = action$ =>
action$.ofType(START_CONTACT_FORM_FIREBASE_SUBMIT)
.flatMap((firebaseSubmitAction) => {
  const values = firebaseSubmitAction.values;
  return merge(
    firebaseAPI.checkUserAndUpdate(values),
    firebaseAPI.setQuoteData(values),
  )
  .takeLast(1)
  .mergeMap((x) => {
    return merge(
        of(contactFormFirebaseSuccess()),
        of(stopLoading()),
      );
  });
});


const firebaseAPI = {

  checkUserAndUpdate: (values) => {
   const checkUserAndUpdateDetails = firebaseRef.once('value', snapshot => {
     const databaseValue = snapshot.val();
     checkUserExistsAndUpdateDetails(databaseValue, values);
    });
   return Observable.from(checkUserAndUpdateDetails);
  },

  setQuoteData: (value) => {
    const setQuote = setQuoteData(values);
    return Observable.from(setQuote);
    },
};

const stopLoading = () => ({ type: STOP_BUTTON_LOADING });
const contactFormFirebaseSuccess = () => ({ type: SUCCESS });

 checkUserAndUpdate: (values, contactsRef) => {
    const checkUser$ = Observable.from(contactsRef.once('value').then( 
    snapshot => {
    const databaseValue = snapshot.val();
    checkUserExistsAndUpdateDetails(
      values,
      databaseValue,
      contactsRef,);
  })
);
     return checkUser$;
 },

const checkUserExistsAndUpdateDetails = (
  values,
  databaseValue,
  contactsRef,
) => {
 if (databaseValue) { console.log('user exists'); }
  else {
     console.log('new user, writing to database');
     contactsRef.set({
      name: values.name,
      email: values.email,
      phone: values.phone,
    });
  }
};

【问题讨论】:

  • checkUserAndUpdateDetails 不是同步的(它需要回调),而 setQuoteData 同步的。所以它会先发送它的值,它不需要回调来完成
  • 您好,但很抱歉没有包含完整的功能,但 setQuoteData 是异步的?但我会说它可能完成得最快,这有关系吗?我以为直到最后一个完成才应该开始?
  • 但我确实看到了你的观点,因为 checkUser... 函数明确地在通过 firebase 的回调中...问题是如果我执行类似 flatMap(do first function).flatMap(do第二个函数)以正确的顺序执行它们,但是在该实例中如何将源值传递给第二个函数?即不是从第一个 flatMap 返回的值?

标签: javascript firebase firebase-realtime-database rxjs redux-observable


【解决方案1】:

问题在于merge 不维护您订阅的流的顺序,它只是从任何源流中发出事件,而不管它们发出什么顺序。

如果您需要维护秩序,您应该使用concat 而不是merge

  const values = firebaseSubmitAction.values;
  return concat(
    firebaseAPI.checkUserAndUpdate(values),
    firebaseAPI.setQuoteData(values),
  )

旁注,我不知道你为什么在那里使用 of 运算符,你已经从你的 API 返回了 Observables,所以在这种情况下你可以将它们传递给 mergeconcat

【讨论】:

  • 这很有意义。我会试试看,干杯!
  • 实际上不,如果用户不存在并且它必须进入 firebase 回调它仍然以错误的顺序出现。我还将 mergeMap 更改为 concatMap 以及合并到 concat 里面
  • 啊啊我的 observables 和 firebase 的设置方式有问题。基本上这些函数以正确的顺序运行,但是'return Observable.from(checkUserAndUpdateDetails);'在回调处理程序触发任何东西之前返回一个可观察对象...我认为这可能比 RXJS 更像是一个火力问题,即如何设置它,以便仅在事件触发时返回一个承诺
  • 您的代码让我有些困惑,您似乎在递归调用您的方法?从回调中?
  • 对不起,我在上面的代码中添加了 checkUser 函数的结构 ^^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-16
相关资源
最近更新 更多