Redux-saga firebase onAuthStateChanged 事件通道

Redux-saga firebase onAuthStateChanged eventChannel

如何在 redux saga 中处理 firebase auth state observer?

firebase.auth().onAuthStateChanged((user) => {

});

我想在我的应用程序启动时 运行 APP_START 传奇,这将 运行 firebase.auth().onAuthStateChanged 观察者和 运行 其他传奇取决于回调。

据我所知,eventChannel 是正确的做法。但我不明白如何让它与 firebase.auth().onAuthStateChanged 一起工作。

有人可以展示如何将 firebase.auth().onAuthStateChanged 放入 eventChannel 吗?

创建您自己的函数 onAuthStateChanged(),它将 return Promise

function onAuthStateChanged() {
  return new Promise((resolve, reject) => {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        resolve(user);
      } else {
        reject(new Error('Ops!'));
      }
    });
  });
}

然后用call方法同步得到user

const user = yield call(onAuthStateChanged);

您可以使用 eventChannel。这是一个示例代码:

function getAuthChannel() {
  if (!this.authChannel) {
    this.authChannel = eventChannel(emit => {
      const unsubscribe = firebase.auth().onAuthStateChanged(user => emit({ user }));
      return unsubscribe;
    });
  }
  return this.authChannel;
}

function* watchForFirebaseAuth() {
  ...
  // This is where you wait for a callback from firebase
  const channel = yield call(getAuthChannel);
  const result = yield take(channel);
  // result is what you pass to the emit function. In this case, it's an object like { user: { name: 'xyz' } }
  ...
}

完成后,您可以使用 this.authChannel.close() 关闭频道。

这可以在 Saga 中处理,例如 Redux Saga Firebase 的以下内容:

// Redux Saga: Firebase Auth Channel
export function* firebaseAuthChannelSaga() {
  try {
    // Auth Channel (Events Emit On Login And Logout)
    const authChannel = yield call(reduxSagaFirebase.auth.channel);

    while (true) {
      const { user } = yield take(authChannel);

      // Check If User Exists
      if (user) {
        // Redux: Login Success
        yield put(loginSuccess(user));
      }
      else {
        // Redux: Logout Success
        yield put(logoutSuccess());
      }
    }
  }
  catch (error) {
    console.log(error);
  }
};

这里是如何使用 redux-saga 特征(主要是 eventChannel

运行 onAuthStateChanged observable
import { eventChannel } from "redux-saga";
import { take, call } from "redux-saga/effects";

const authStateChannel = function () {
  return eventChannel((emit) => {
    const unsubscribe = firebase.auth().onAuthStateChanged(
      (doc) => emit({ doc }),
      (error) => emit({ error })
    );

    return unsubscribe;
  });
};

export const onAuthStateChanged = function* () {
  const channel = yield call(authStateChannel);

  while (true) {
    const { doc, error } = yield take(channel);
    if (error) {
      // handle error
    } else {
      if (doc) {
        // user has signed in, use `doc.toJSON()` to check
      } else {
        // user has signed out
      }
    }
  }
};

请注意,其他不使用 channel sagas 的解决方案对于 redux-saga 而言并不是最佳解决方案,因为在这种情况下将可观察对象转化为 promise 不是有效的解决方案,因为您需要调用 promise每次您预期身份验证状态发生变化时(例如:采取每个 USER_SIGNED_IN 操作并调用“promisified”可观察对象),这将否定可观察对象的全部目的