史诗中的功能乱序执行,我不明白为什么
Functions in epic are firing out of order and I can't understand why
*已解决
问题在于我如何创建和响应由 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 函数之前运行。有谁知道为什么会这样?
此外,如果有更好的方法来展示它,我会非常乐意接受建议!干杯。此外,我还删除了很多变量和会使它变得更加复杂的东西。基本上我只是想表明在每种情况下我都从 'doing something with 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
在这种情况下。
*已解决 问题在于我如何创建和响应由 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 函数之前运行。有谁知道为什么会这样?
此外,如果有更好的方法来展示它,我会非常乐意接受建议!干杯。此外,我还删除了很多变量和会使它变得更加复杂的东西。基本上我只是想表明在每种情况下我都从 'doing something with 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
在这种情况下。