javascript - 史诗中的函数不按顺序触发,我不明白为什么

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

*已解决 问题在于我如何创建和响应由 firebase 回调创建的可观察对象。 我的 firebase 回调中也发生了太多的事情。 我最终使用 firebase Promise 结构将其进一步拆分: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,
    });
  }
};

最佳答案

问题是 merge 不会维护您订阅的流的顺序,它只是从任何源流中发出事件,无论它们发出的顺序如何。

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

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

旁注,我不知道你为什么在那里使用of运算符,你已经从API返回了Observables,所以你可以将它们传递给merge或在本例中concat

关于javascript - 史诗中的函数不按顺序触发,我不明白为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41275910/

相关文章:

javascript - 操作 RxJS 流并发布结果的 Observable 的正确方法是什么?

android - android 上的 firebase 设置

javascript - 保存并获取 Firebase 集合中项目的 $priority AngularFire 0.6.0

javascript - Firebase 错误 : Uncaught TypeError: ref. once is not a function

javascript - JQM pagebeforeshow 事件调用两次

javascript - 内容丰富 + Angular2

android - remoteMessage.getNotification().getBody() 出错

firebase - 在客户端编写业务逻辑是否存在安全问题

java - 如何将 Firebase 数据与登录身份验证屏幕输入进行比较。安卓

javascript - 如何使 push、unshift、pop 和 shift 仅适用于 javascript 中的本地数组?