0

下面的代码是否是使用 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)
4

2 回答 2

0

使用 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 });
    }
  }
}
于 2018-01-08T01:09:34.477 回答
0

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

于 2018-01-06T20:23:28.360 回答