Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 从一个redux传奇中调用两种不同的动作类型_Reactjs_Redux_Redux Saga - Fatal编程技术网

Reactjs 从一个redux传奇中调用两种不同的动作类型

Reactjs 从一个redux传奇中调用两种不同的动作类型,reactjs,redux,redux-saga,Reactjs,Redux,Redux Saga,我现在已经能够通过基本的sagas实现了,但是我的应用程序变得有点复杂了。我选择sagas作为异步功能,但似乎误解了事情的工作原理 我的应用程序中有一个全局搜索输入,需要进行两个不同的api调用(不同的数据对象),但搜索输入也有自己的加载状态,具体取决于api调用的搜索/状态。基于此信息,这是应用程序的流程: 搜索发生(发送操作全局搜索请求) GLOBAL\u SEARCH\u REQUEST的saga watcher启动(将输入的加载设置为true) 在这个故事中-调用以获取与搜索查询匹配的所

我现在已经能够通过基本的sagas实现了,但是我的应用程序变得有点复杂了。我选择sagas作为异步功能,但似乎误解了事情的工作原理

我的应用程序中有一个全局搜索输入,需要进行两个不同的api调用(不同的数据对象),但搜索输入也有自己的加载状态,具体取决于api调用的搜索/状态。基于此信息,这是应用程序的流程:

  • 搜索发生(发送操作
    全局搜索请求
  • GLOBAL\u SEARCH\u REQUEST
    的saga watcher启动(将输入的加载设置为true)
  • 在这个故事中-调用以获取与搜索查询匹配的所有用户/订阅
  • 成功后,将输入的加载设置为false
  • 失败时,设置错误
  • 全球搜索请求传奇

    function* globalSearchRequestSaga(action) {
      const { query } = action
      console.log(`searching subscriptions and users for : ${query}`)
      try {
        yield put(fetchUsersRequest(query))
        // call for the subscriptions (leaving it out for simplicity in this example)
        yield put(globalSearchSuccess(query))
      } catch (error) {
        console.log(`error: ${error}`)
        yield put(globalSearchFailure(error.message))
      }
    }
    
    fetch users传奇看起来像什么

    export function* fetchUsersRequestSaga(action) {
      const { query } = action
      const path = `${root}/users`
      try {
        const users = yield axios.get(path, { crossDomain: true })
        yield put(fetchUsersSuccess(query, users.data))
      } catch (error) {
        console.log(`error : ${error}`)
        yield put(fetchUsersFailure(query, error.message))
      }
    }
    
    (非常基本)

    如果我这样做,就会出现一个问题,
    GLOBAL\u SEARCH\u SUCCESS
    操作在用户请求完成之前执行(如果我也在订阅api调用中添加了此操作,我会想到同样的问题)。我找到的一个解决办法是,如果我改变路线

    yield put(fetchUsersRequest(query))
    

    其中,
    fetchUsersRequestSaga
    是上面的saga,而
    fetchUsersRequest(query)
    是获取用户的操作创建者。这会导致asnyc功能正常工作,并等待用户返回(正确行为)

    唯一的问题是,
    FETCH\u USERS\u请求
    操作不再记录到存储中


    我想知道是否有一种方法可以让它正确地登录到存储,或者返回到我以前的实现,并在
    put(fetchUsersRequest(query))

    上进行适当的阻塞
    put
    函数是一种非阻塞操作。它不会等到promise/api请求得到解决

    我建议你直接给萨加斯打电话,而不是采取行动

    try {
       yield call(fetchUsersRequestSaga, query);
       yield call(globalSearchSaga, query); // or whatever its called
    }
    

    调用
    是一种阻塞操作。它将一直等到请求完成,因此无论您的调用是否按正确的顺序执行。

    我使用sagas已经有一段时间了,但下面的一些代码将让您大致了解如何等待已调度的操作

    它的工作方式是,当您获取并希望等待它失败或成功时,为获取操作提供一个id,然后您可以将该id传递给waitFor函数,同时分派该操作

    如果您不想或不需要等待它,那么您可以在没有id的情况下发送操作,它仍然可以工作:

    const addId = (id => fn => (...args) => ({
      ...fn(...args),
      id: id++,
    }))(0);
    const withId = ({ id }, action) => ({ action, id });
    
    function* waitFor(id) {
      const action = yield take('*');
      if (action.id === id) {
        return action;
      }
      return waitFor(id);
    }
    
    function* globalSearchRequestSaga(action) {
      const { query } = action;
      console.log(
        `searching subscriptions and users for : ${query}`
      );
      try {
        //add id to action (id is unique)
        const action = addId(fetchUsersRequest, query);
        //dispatch the action and then wait for resulting action
        //  with the same id
        yield put(action);
        const result = yield waitFor(action.id);
        // call for the subscriptions (leaving it out for simplicity in this example)
        yield put(globalSearchSuccess(query));
      } catch (error) {
        console.log(`error: ${error}`);
        yield put(globalSearchFailure(error.message));
      }
    }
    
    export function* fetchUsersRequestSaga(action) {
      const { query } = action;
      const path = `${root}/users`;
      try {
        const users = yield axios.get(path, {
          crossDomain: true,
        });
        yield put(//add original id to success action
          withId(action, fetchUsersSuccess(query, users.data))
        );
      } catch (error) {
        console.log(`error : ${error}`);
        yield put(
          withId(//add original id to fail action
            action,
            fetchUsersFailure(query, error.message)
          )
        );
      }
    }
    

    您可以生成一个关于获取用户的成功或失败,但由于您放置了多个获取用户操作,因此您必须等待您刚刚触发的准确的成功或失败,这意味着为您的获取用户操作提供一个id,并让成功和失败使用该id。因此,您在
    fetchUsersRequestSaga
    do
    yield-take中这样说(FetchUsersAccess(query,users.data)
    这会阻止另一个传奇中
    globalSearchSuccess()
    的执行吗?我添加了一个答案,让我知道这是否有效。不久前在一个通用api层中做了类似的事情,因此可能错过了一些收益(可能waitFor需要
    返回收益waitFor(id))
    当它递归调用自身时。OP已尝试调用,但未调度fetch user,且从未调用fetch user的减缩器。@HMR那么为什么不将“fetch user逻辑”移动到saga中?或者只在saga中调度它,但断开
    globalSearchRequestSaga
    从侦听该操作的连接。在哪里他的名字是从哪里来的?是的!因为我正在处理两个传奇,用户和搜索,你说在这次尝试中调用这两个传奇(我想我会从
    searchSaga
    中调用他们)@erp您必须在
    globalSearchRequestSaga
    中给他们打电话,就像您在上面做的那样。但是打电话而不是采取行动。谢谢您的回复。我需要一些时间来查看this@erp我编辑了答案,我认为它是
    yieldall([put(action),call(waitFor(action.id)));
    如果要分派一个获取操作并等待另一个id相同的操作(成功或失败)。可能
    产生put(操作);yied调用(waitFor(action.id)))
    也可以,但我不确定。我认为这可能有点过于复杂了problem@erp查看了旧代码并更新了答案,您可以调度fetch操作,然后执行
    const result yield waitFor(刚刚调度的操作的id)
    ,结果将是fetch saga将分派的成功或失败操作。
    const addId = (id => fn => (...args) => ({
      ...fn(...args),
      id: id++,
    }))(0);
    const withId = ({ id }, action) => ({ action, id });
    
    function* waitFor(id) {
      const action = yield take('*');
      if (action.id === id) {
        return action;
      }
      return waitFor(id);
    }
    
    function* globalSearchRequestSaga(action) {
      const { query } = action;
      console.log(
        `searching subscriptions and users for : ${query}`
      );
      try {
        //add id to action (id is unique)
        const action = addId(fetchUsersRequest, query);
        //dispatch the action and then wait for resulting action
        //  with the same id
        yield put(action);
        const result = yield waitFor(action.id);
        // call for the subscriptions (leaving it out for simplicity in this example)
        yield put(globalSearchSuccess(query));
      } catch (error) {
        console.log(`error: ${error}`);
        yield put(globalSearchFailure(error.message));
      }
    }
    
    export function* fetchUsersRequestSaga(action) {
      const { query } = action;
      const path = `${root}/users`;
      try {
        const users = yield axios.get(path, {
          crossDomain: true,
        });
        yield put(//add original id to success action
          withId(action, fetchUsersSuccess(query, users.data))
        );
      } catch (error) {
        console.log(`error : ${error}`);
        yield put(
          withId(//add original id to fail action
            action,
            fetchUsersFailure(query, error.message)
          )
        );
      }
    }