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

How to use redux-thunk middleware async actions with the new js async/await syntax

我正在尝试了解 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))
      )
  }
}

关于该评论,吞下反应异常是一个常见的错误,这是我试图避免的……我正在尝试在这里使用新的 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));
  }
}

但是在出现错误的情况下,我不确定行为是否与没有 async/await 的示例相同。我不确定是否需要将 return 放在 catch 块中。示例 returns 是一个承诺,我不确定我的代码是否仍然如此。

搜索了一下,只找到了使用generators/yield语法的this question but without response, and I found a redux-saga组件。我应该使用 redux-saga 而不是 redux-thunk 和 async/await?

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

您只捕获来自 fetch() 调用本身的错误,如果出现错误,记录它并在那里停止。假设没有错误,它会调度操作。是的,所有 async 都会自动运行 return 承诺。

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

我的感觉是原来的代码其实应该是

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 解析的替代(并且无条件地后跟使用可能未定义的 json 值进行调度)。

这种分支 ,所以我只保留 then 语法。如果你想重写它,你的第二次尝试是好的(相当于我更正的 then 语法),但你需要在 try 块之外声明 json (或使用 var 而不是 const):

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