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
Javascript 如何使用redux saga处理异步API调用?_Javascript_Reactjs_Asynchronous_Redux_Redux Saga - Fatal编程技术网

Javascript 如何使用redux saga处理异步API调用?

Javascript 如何使用redux saga处理异步API调用?,javascript,reactjs,asynchronous,redux,redux-saga,Javascript,Reactjs,Asynchronous,Redux,Redux Saga,最近,我们开始使用redux saga中间件来管理来自应用商店的异步API调用 以前,我们使用了基于承诺的通用操作,一旦我们可以在操作本身上使用async/await和.then()和.catch()就可以轻松地管理组件流 承诺: const fetchCars = async () => { const {data} = await fetchCarsRequest(); setCars(data); } cars.map((car) => <li>{c

最近,我们开始使用redux saga中间件来管理来自应用商店的异步API调用

以前,我们使用了基于承诺的通用操作,一旦我们可以在操作本身上使用
async/await
.then()
.catch()
就可以轻松地管理组件流

承诺:

const fetchCars = async () => {
  const {data} = await fetchCarsRequest();
  
  setCars(data);
}

cars.map((car) => <li>{car.name}</li>);
const fetchCars=async()=>{
const{data}=wait fetchCarsRequest();
setCars(数据);
}
cars.map((car)=>
  • {car.name}
  • );
    关于传奇故事:

    function* fetchCarsSaga() {
      try {
        const {data} = yield call(fetchCarsService);
    
        yield put(fetchCarsSuccess);
      } catch(error) {
        yield put(fetchCarsFailure);
      } 
    }
    
    const fetchCars = async () => {
     fetchCarsRequest(); //action that calls the above saga
    
     setCars(cars); //state from store 
    }
    
    cars.map((car) => <li>{car.name}</li>);
    
    函数*fetchCarsSaga(){
    试一试{
    const{data}=产生调用(fetchCarsService);
    收益率看跌期权(FetchCarsAccess);
    }捕获(错误){
    收益率看跌期权(FETCHARSFAILURE);
    } 
    }
    const fetchCars=async()=>{
    fetchCarsRequest();//调用上述事件的操作
    setCars(cars);//从商店中声明
    }
    cars.map((car)=>
  • {car.name}
  • );
    在第二个示例中,即使我们使用生成器来处理异步API调用,也不可能使用
    wait
    语句,因此它在调用
    fetchCarsRequest
    之后立即调用
    setCars
    函数,试图将尚不存在的内容设置为组件状态


    因此,我的问题是:有没有一种方法可以替换
    await
    语句,然后等待请求函数(这不是异步函数)完成API调用?

    使用redux saga,流程会有所不同。您不能在组件中直接使用生成器。您需要从saga中更新redux状态,并在组件中获取它

    react component -> redux action -> saga -> redux state -> react component
    
    PT-BR中的两篇文章是:

    一个好的
    create react app
    模板是:

    在代码沙盒中:

    终止组件状态 您希望分派一个操作
    fetchCarsRequest()
    ,该操作将触发API调用并将结果保存到redux存储中。您需要等待此操作完成,然后调用
    setCars(cars)
    将组件状态设置为redux状态的值。为什么?

    这是一种反模式。数据已经存在于redux中,应该直接从组件中的redux访问。您应该使用
    use selector
    connect
    HOC从redux选择
    cars
    的值。一旦您的fetch已调度
    fetchcarssaccess
    并更新了存储状态,它将自动使用新数据重新呈现组件

    应该是这样的

    传奇

    组成部分

    const Cars = () => {
       const dispatch = useDispatch();
       const cars = useSelector( state => state.cars.data ) || [];
       const isLoading = useSelector( state => state.cars.isLoading );
       const error = useSelector( state => state.cars.error );
    
       useEffect( () => {
          dispatch(fetchCarsRequest()); // action that calls the saga
       }, [] );
    
    
       return (
          {!! error && (<div>Error: {error}</div>)}
          {isLoading ? <Spinner/> : (
            <ul>
              {cars.map((car) => <li key={car.id}>{car.name}</li>)}
            </ul>
          )}
       )
    }
    
    const Cars=()=>{
    const dispatch=usedpatch();
    const cars=useSelector(state=>state.cars.data)| |[];
    const isLoading=useSelector(state=>state.cars.isLoading);
    const error=useSelector(state=>state.cars.error);
    useffect(()=>{
    dispatch(fetchCarsRequest());//调用传奇的操作
    }, [] );
    返回(
    {!!错误&(错误:{error})}
    {正在加载?:(
    
      {cars.map((car)=>
    • {car.name}
    • )}
    )} ) }
    不清楚您到底在问什么-您使用的名称与代码中的函数/生成器名称不完全匹配这一事实没有帮助。但是redux saga的
    调用
    将自动“等待”一个承诺,如果被调用的函数返回一个承诺-就像所有
    异步
    函数一样。如果在调用
    fetchCarsRequest
    之前放置
    wait
    (因此该函数隐式返回的承诺直到
    fetchCarsRequest
    解决后才会解决),那么我认为一切都应该正常工作?我想我无法很好地表达自己。我的主要疑问是,一旦saga处理异步调用,如何等待API调用完成,而不使用
    wait
    ,调用另一个函数。例如,我想等待saga完成API调用并将状态设置为store,以打开一个成功模式。我该怎么做呢?@Gabriel在我看来
    useffect
    是“正确”的方法,所以我不确定你为什么要做其他事情。中间件使得您可以
    等待
    调度
    。我不认为redux传奇也有同样的效果,但我从未尝试过。你们完全正确。它确实解决了
    useffect
    的问题,但仅在这种情况下。事实上,我在几乎所有一开始就必须发出API请求的组件中都这样做,我的问题是:如何等待saga完成API调用并将状态设置为存储,然后才打开一个成功模式,例如?在这种情况下,只需单击按钮即可调用请求。谢谢@oieduardorabelo的回复。这些文章真的很有用。但我的问题是:例如,如何等待saga完成API调用并将状态设置为存储,然后才打开成功模式?在这种情况下,调用该传奇的操作只需单击按钮即可调用。@GabrielSantana,您需要在redux状态下控制该操作。假设你的传奇用
    yield-put({type:“CAR\u-MODAL\u-OPEN”})更新redux状态
    ,这个动作会触发一个reducer,该reducer使用
    {modals:{CAR:“OPEN”}}}
    返回新状态,然后在你的react组件中,你可以将这个状态映射到道具,在渲染函数中,您可以检查
    props.carModal===“open”
    以渲染所需的任何内容。循环
    react component->redux action->saga->redux state->react component
    是状态如何流动/更新的。是的。事实上,它确实解决了问题。但它仍然在减速器内部处理,具有全局状态,而不是在调用减速器的组件内部。也许没有一种方法像
    wait
    那样等待。我猜在sagas中,你必须一直跟踪edux状态的变化,才能在
    u中做一些事情
    
    const Cars = () => {
       const dispatch = useDispatch();
       const cars = useSelector( state => state.cars.data ) || [];
       const isLoading = useSelector( state => state.cars.isLoading );
       const error = useSelector( state => state.cars.error );
    
       useEffect( () => {
          dispatch(fetchCarsRequest()); // action that calls the saga
       }, [] );
    
    
       return (
          {!! error && (<div>Error: {error}</div>)}
          {isLoading ? <Spinner/> : (
            <ul>
              {cars.map((car) => <li key={car.id}>{car.name}</li>)}
            </ul>
          )}
       )
    }