如何使用具有新的js async / await语法的redux-thunk中间件异步操作

时间:2018-07-31 16:11:54

标签: javascript redux async-await react-redux redux-thunk

我正在尝试了解redux中的异步操作。读this page,我得到以下示例:

export function fetchPosts(subreddit) {
  return (dispatch) => {
​
    dispatch(requestPosts(subreddit))
​
    return fetch(`https://www.reddit.com/r/${subreddit}.json`)
      .then(
        response => response.json(),
        // Do not use catch, because that will also catch
        // any errors in the dispatch and resulting render,
        // causing a loop of 'Unexpected batch number' errors.
        // https://github.com/facebook/react/issues/6895
        error => console.log('An error occurred.', error)
      )
      .then(json =>
        dispatch(receivePosts(subreddit, json))
      )
  }
}

关于该评论,吞咽React异常是一个常见的错误,我正在尝试避免...在这里尝试使用新的javascript async / await语法...行为完全一样吗?

我首先想到了这一点:

export function fetchPosts(subreddit) {
​
  return async (dispatch) => {

    dispatch(requestPosts(subreddit));
    try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
      dispatch(receivePosts(subreddit, json));
    }
    catch (error) {
      console.log('An error occurred.', error);
    }
  }
}

但是我有种感觉,这正是评论所要避免的。然后我想到了这段代码:

export function fetchPosts(subreddit) {
​
  return async (dispatch) => {

    dispatch(requestPosts(subreddit));

    try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
    }
    catch (error) {
      console.log('An error occurred.', error);
      return;
    }

    dispatch(receivePosts(subreddit, json));
  }
}

但是在发生错误的情况下,我不确定行为是否与没有异步/等待的示例相同。我不确定是否需要将return放在catch块中。该示例返回了一个承诺,我不确定我的代码是否仍会发生。

在搜索它时,我仅发现this question但没有响应,并且发现了一个使用生成器/ yield语法的redux-saga组件。我应该在异步/等待时使用redux-saga而不是redux-thunk吗?

2 个答案:

答案 0 :(得分:1)

是的,我相信您的第二个示例等效于基于promise的代码段,尽管存在语法错误。

您仅从fetch()调用本身中捕获错误,并且在出现错误的情况下,将其记录并停止在那里。假设没有错误,则调度该动作。是的,所有async函数都会自动返回一个Promise。

错误是const json = await response.json()是块作用域的,因此json变量将不能在try {}块之外访问。您希望在let json;之前声明try,以便以后可以引用它。

答案 1 :(得分:1)

我的感觉是原始代码实际上应该是

export function fetchPosts(subreddit) {
  return (dispatch) => {
    dispatch(requestPosts(subreddit));
    return fetch(`https://www.reddit.com/r/${subreddit}.json`)
      .then(response =>
        response.json()
      )
      .then(json =>
        dispatch(receivePosts(subreddit, json))
      , error => {
        // Do not use catch, because that will also catch
        // any errors in the dispatch and resulting render,
        // causing a loop of 'Unexpected batch number' errors.
        // https://github.com/facebook/react/issues/6895
        console.log('An error occurred.', error)
      });
  }
}

其中错误处理程序是receivePosts(subreddit, json)调度的替代,而不是JSON解析的替代方法(并且无条件地进行调度,可能带有未定义的{{1} }值。

这种分支is hard to achieve with try/catch when using async/await,所以我只保留json语法。如果您想重写它,则可以进行第二次尝试(相当于我更正后的then语法),但是您需要在then块之外声明json(或使用{ {1}}代替try):

var