【问题标题】:Unable to catch error using redux-saga? (while making a firestore call via react-native-firestore)无法使用 redux-saga 捕获错误? (通过 react-native-firestore 进行 firestore 调用时)
【发布时间】:2018-06-15 20:47:15
【问题描述】:

下面的代码是否是使用 call 或 fork 在 redux-saga 中“捕获”错误的正确方法?那就是当我有“createItem”函数时,这里不捕获任何错误是正确的,并假设这会将任何异常传递回生成器函数“createItemSaga”以捕获?

这里的第二个问题是我注意到我收到了传回的 Firestore 错误(我正在使用 react-native-firebase),但是我没有用这段代码捕捉到它。请参阅下面的控制台输出。我创建了一个安全规则来拒绝在 Firestore 后端创建项目的尝试以对此进行测试。

function createItem(item) {
  firebase.firestore().collection('todos').add(item);
}

export function* createItemSaga() {
  while (true) {
    const action = yield take(ActionTypes.AddListItem_UIRequest);
    console.log('createItemSaga: received AddListItem_UIRequest');
    const { item } = action;    
    yield put({ type: ActionTypes.AddListItemRequested });

    try {
      console.log('createItemSaga: createItem Start');
      yield fork(createItem, item);
      console.log('createItemSaga: createItem Ended');  // <-- This is reached! But why.
    } catch (e) {
      console.log('createItemSaga: error caught. Error=');  <-- Why isn't this point reached
      console.log(pf(e));
      yield put({ type: ActionTypes.AddListItemRejected });
    }
  }
}

控制台输出为:

createItemSaga: recived AddListItem_UIRequest
createItemSaga: createItem Start
createItemSaga: createItem Ended

Possible Unhandled Promise Rejection (id: 0):
Error: Firestore: The caller does not have permission to execute the specified operation. (firestore/permission-denied).
Error: Firestore: The caller does not have permission to execute the specified operation. (firestore/permission-denied).
    at createErrorFromErrorData (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1822:15)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1775:25
    at MessageQueue.__invokeCallback (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:2133:16)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1950:16
    at MessageQueue.__guard (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:2068:9)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1949:12)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/debuggerWorker.js:126:58
    at process.<anonymous> (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/debuggerWorker.js:35:9)
    at emitTwo (events.js:125:13)
    at process.emit (events.js:213:7)

注意:这里是否提出了潜在问题是与此库相关的情况:https://github.com/invertase/react-native-firebase/issues/727

附加说明:

  • 如果我在“yield fork(createItem, item);”行中使用“call”而不是“fork”,我会得到相同的结果
  • 如果我将更新尝试合并到生成中,我也会得到相同的结果,如下所示:

代码:

export function* createItemSaga() {
  while (true) {
    const action = yield take(ActionTypes.AddListItem_UIRequest);
    const { item } = action;
    yield put({ type: ActionTypes.AddListItemRequested });
    try {
      console.log('createItemSaga: createItem Start');
      firebase.firestore().collection('todos').add(item);
      console.log('createItemSaga: createItem Ended');
    } catch (e) {
      console.log('createItemSaga: error caught. Error='); 
      console.log(pf(e));
      yield put({ type: ActionTypes.AddListItemRejected });
    }
  }
}

附加说明 2:

  • 当我将“createItem”函数转换为生成器时得到相同的结果:

代码:

export function* createItem(item) {
  try {
    console.log('createItem: Start');
    firebase.firestore().collection('todos').add(item);
    console.log('createItem: End');
  } catch (e) {
    console.log('createItem: error');
    console.log(pf(e));
  }
}

    export function* createItemSaga() {
      while (true) {
        const action = yield take(ActionTypes.AddListItem_UIRequest);
        const { item } = action;
        yield put({ type: ActionTypes.AddListItemRequested });

        try {
          console.log('createItemSaga: createItem Start');
          yield call(createItem, item);
          console.log('createItemSaga: createItem Ended');
        } catch (e) {
          console.log('createItemSaga: error caught. Error='); 
          console.log(pf(e));
          yield put({ type: ActionTypes.AddListItemRejected });
        }
      }
    }

控制台:

createItemSaga: createItem Start
createItem: Start
createItem: End
createItemSaga: createItem Ended
Possible Unhandled Promise Rejection (id: 0):
Error: Firestore: The caller does not have permission to execute the specified operation. (firestore/permission-denied).
Error: Firestore: The caller does not have permission to execute the specified operation. (firestore/permission-denied).
    at createErrorFromErrorData (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1822:15)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1775:25
    at MessageQueue.__invokeCallback (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:2133:16)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1950:16
    at MessageQueue.__guard (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:2068:9)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/index.bundle:1949:12)
    at /Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/debuggerWorker.js:126:58
    at process.<anonymous> (/Users/Greg/Dropbox/source_reactnative/gcTodo/.vscode/.react/debuggerWorker.js:35:9)
    at emitTwo (events.js:125:13)
    at process.emit (events.js:213:7)

【问题讨论】:

    标签: redux-saga react-native-firebase


    【解决方案1】:

    首先我认为createItem 应该是一个生成器(或者换句话说,一个传奇)。然后你不需要fork,而是call。那是因为fork 没有阻塞,而call 是。这就是您获取控制台日志的原因。我猜如果createItem 是一个生成器,你的try-catch 块就可以工作。

    【讨论】:

    • 如果我在 "yield fork(createItem, item);" 行中使用 "call" 而不是 "fork" 会得到相同的结果
    • 如果我将更新行合并到生成器中也会得到相同的结果 - 将此代码放在问题的末尾以显示
    • 如果现在这表明我用于 firebase 的底层 react-native-firebase 库中存在错误,则不是这个?即,这是否确认它是这个库没有正确捕获错误,或者我们正在查看的我的 redux-saga 代码是否应该在任何情况下捕获这个异常?
    • 但是你把createItem 做成了一个生成器吗?喜欢function* createItem
    • 是的,我得到与生成器相同的结果。我把代码放在问题的最后(如果这是你的意思?)
    【解决方案2】:

    使用 createItem 作为一个单独的函数并没有让它工作,但是现在我通过将所有内容收缩到一个生成器中来捕获错误:

    export function* createItemSaga() {
      while (true) {
        const action = yield take(ActionTypes.AddListItem_UIRequest);
        const { item } = action;
        yield put({ type: ActionTypes.AddListItemRequested });
        try {
          const ref = firebase.firestore().collection('todos');
          yield call([ref, ref.add], item);
          yield put({ type: ActionTypes.AddListItemFulfilled });
        } catch (e) {
          console.log('createItemSaga: error caught. Error='); 
          console.log(pf(e));
          yield put({ type: ActionTypes.AddListItemRejected });
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 1970-01-01
      • 2019-06-18
      • 2018-09-01
      • 1970-01-01
      相关资源
      最近更新 更多