Redux 传奇:yield put 在嵌套回调中不起作用
Redux saga: yield put not working inside nested callback
const { payload: {loginType, email, password, notification, self} } = action;
console.log("--TRY--");
Firebase.login(loginType, { email, password })
.catch(function(result) {
const message =
result && result.message ? result.message : 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
isError = true;
})
.then(function(result) {
if (isError) {
return;
}
if (!result || result.message) {
const message =
result && result.message
? result.message
: 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
} else {
self.setState({
visible: false,
confirmLoading: false
});
console.log("--RIGHT BEFORE I CHECK AUTH STATE--");
//the following does NOT fire
firebaseAuth().onAuthStateChanged(function*(user) {
console.log("THE GENERATOR RUNS");
if (user) {
console.log(user);
yield put({
type: actions.LOGIN_SUCCESS,
token: 'secret token',
profile: 'Profile'
});
yield put(push('/dashboard'));
}
else {
yield put({ type: actions.LOGIN_ERROR });
}
});
}
}); });
你好。我目前是第一次使用 redux saga。我一直在尝试在 firebaseAuth().onAuthStateChanged 侦听器的回调中触发 yield。 yield 关键字在非 ES6 生成器的函数中不起作用,因此我在回调中添加了一个星号,但现在它根本不会执行。非常感谢有关此事的任何建议。
如您所见,redux-saga effects 只能在生成器函数中使用,不能将生成器函数用作常规函数:仅调用生成器函数 returns 特殊对象。
解决此问题的正确方法是使用 eventChannel
:它可以让您将 saga 连接到 redux 生态系统外部的事件源。
首先使用提供的工厂函数创建您的 eventChannel
:它会为您提供一个 emit
函数,您可以使用它来发出事件;然后使用 take
效果消耗这些事件。
import { eventChannel } from 'redux-saga';
import { cancelled, take } from 'redux-saga/effects';
// first create your eventChannel
const authEventsChannel = eventChannel( emit => {
const unsubscribe = firebaseAuth().onAuthStateChanged( user => {
emit({ user });
});
// return a function that can be used to unregister listeners when the saga is cancelled
return unsubscribe;
});
// then monitor those events in your saga
try {
while (true) {
const { user } = yield take (authEventsChannel);
// handle auth state
}
} finally {
// unregister listener if the saga was cancelled
if (yield cancelled()) authEventsChannel.close();
}
const { payload: {loginType, email, password, notification, self} } = action;
console.log("--TRY--");
Firebase.login(loginType, { email, password })
.catch(function(result) {
const message =
result && result.message ? result.message : 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
isError = true;
})
.then(function(result) {
if (isError) {
return;
}
if (!result || result.message) {
const message =
result && result.message
? result.message
: 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
} else {
self.setState({
visible: false,
confirmLoading: false
});
console.log("--RIGHT BEFORE I CHECK AUTH STATE--");
//the following does NOT fire
firebaseAuth().onAuthStateChanged(function*(user) {
console.log("THE GENERATOR RUNS");
if (user) {
console.log(user);
yield put({
type: actions.LOGIN_SUCCESS,
token: 'secret token',
profile: 'Profile'
});
yield put(push('/dashboard'));
}
else {
yield put({ type: actions.LOGIN_ERROR });
}
});
}
}); });
你好。我目前是第一次使用 redux saga。我一直在尝试在 firebaseAuth().onAuthStateChanged 侦听器的回调中触发 yield。 yield 关键字在非 ES6 生成器的函数中不起作用,因此我在回调中添加了一个星号,但现在它根本不会执行。非常感谢有关此事的任何建议。
如您所见,redux-saga effects 只能在生成器函数中使用,不能将生成器函数用作常规函数:仅调用生成器函数 returns 特殊对象。
解决此问题的正确方法是使用 eventChannel
:它可以让您将 saga 连接到 redux 生态系统外部的事件源。
首先使用提供的工厂函数创建您的 eventChannel
:它会为您提供一个 emit
函数,您可以使用它来发出事件;然后使用 take
效果消耗这些事件。
import { eventChannel } from 'redux-saga';
import { cancelled, take } from 'redux-saga/effects';
// first create your eventChannel
const authEventsChannel = eventChannel( emit => {
const unsubscribe = firebaseAuth().onAuthStateChanged( user => {
emit({ user });
});
// return a function that can be used to unregister listeners when the saga is cancelled
return unsubscribe;
});
// then monitor those events in your saga
try {
while (true) {
const { user } = yield take (authEventsChannel);
// handle auth state
}
} finally {
// unregister listener if the saga was cancelled
if (yield cancelled()) authEventsChannel.close();
}