React Redux with SAGA - 创建相同动作的队列

React Redux with SAGA - Create a queue of the same action

我有一个应用程序,每次检索 axios 50 个项目的数据并对它们进行分页。最初我打了两个电话,第一次准备当前页面(25 项),第二次准备下一页(25 项)。

然后每次用户点击下一页时,它都会调用其他 50 个项目,依此类推。

因此该应用会“在幕后”检索数据并准备下一页以获得更好的用户体验。

我的问题是,我如何使用 SAGA 创建呼叫队列?

如果用户多次点击下一页,我的调用“拥塞”可能(已经测试)第 3 次在第 4 次之后结束,那么数据不按顺序。

我想要的是:

1 call => end =>
2 call => end =>
3 call => end =>
4 call => end =>

等等...

我用的函数是setSpotifyData()

那是我的代码:

// first call just for the token and when the token expires

function* getSpotifyData(obj) {
  try {
    yield put({
      type: "GET_SPOTIFY_USER_DATA_SUCCESS",
      payload: obj.payload,
    });
  } catch (error) {
    yield put({ type: "GET_SPOTIFY_USER_DATA_ERROR", payload: error });
  }
}

// 我想“排队”的函数:

function* setSpotifyData(obj) {
  const url = "http://localhost:8888/api/spotifyuserdata";

  // route the needs auth
  const config = {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${obj.payload.token}`,
    },
    // becomes query in the route
    params: obj.payload,
    url: url,
    transformResponse: [
      (data) => {
        return data;
      },
    ],
  };

  try {
    const spotifyData = yield axios(config);
    /**
     * @description Remapping to make it lighter
     */

    ...code...

    yield put({
      type: "SET_SPOTIFY_USER_DATA_SUCCESS",
      payload: newAlbumsArr,
    });
    return newAlbumsArr;
  } catch (error) {
    yield put({ type: "SET_SPOTIFY_USER_DATA_ERROR", payload: error });
  } finally {
    yield put({ type: "SET_SPOTIFY_USER_DATA_END" });
  }
}

function* watchAllSpotifyUserDataSaga() {
  yield takeEvery("GET_SPOTIFY_USER_DATA", getSpotifyData);
  yield takeEvery("SET_SPOTIFY_USER_DATA", setSpotifyData);
}

export default watchAllSpotifyUserDataSaga;

我已经尝试使用 SAGA 的 throttle。但实际上并没有改变。

我也想在加载时禁用按钮,但我想尝试一下并学习一些新东西。

提前致谢

您正在使用 takeEvery 帮助程序,它执行所有 GET_SPOTIFY_USER_DATA 操作并调用 getSpotifyData 但问题是它允许 同时调用多个 getSpotifyData 实例 。换句话说,您可能会在上一个任务尚未终止时开始新任务,这就是为什么您的数据顺序可能不正确的原因。

您可以使用 actionChannel 效果,根据文档,它会生成一个动作队列并一个一个地执行它们。这意味着我们在处理完上一个动作后执行下一个动作。

为此,您需要在 getSpotifyData 函数中创建一个频道

function* getSpotifyData(obj) {
  const usersChannel = yield actionChannel('GET_SPOTIFY_USER_DATA')

  while (true) {
   try {
    const {payload} = yield take(usersChannel)

    yield call(setSpotifyData, payload)
  } catch (error) {
    console.error('some error:', error)
  }
}

您通过 put 发送到存储的来自 getSpotiFyData 的操作需要移动到您的 worker saga,即 setSpotiFyData,如果您需要的话。

你的 saga watchAllSpotifyUserDataSaga 现在也需要修改。

您可以改写如下:

export default function* watchAllSpotifyUserDataSaga() {
  yield all([
    getSpotiFyData(),
    //some other sagas but I don't think you need to include setSpotifyData here
    //as it's called from the other saga
  ])
}