在 react redux saga 中处理同步

Posted

技术标签:

【中文标题】在 react redux saga 中处理同步【英文标题】:Handle Sync in react redux saga 【发布时间】:2019-03-03 15:06:39 【问题描述】:

用户将输入姓名电子邮件和订单信息,包括付款详情。 在单击表单中的“立即购买”按钮时,我计划执行以下步骤:

通过 api 调用创建用户。 自动登录并通过以下方式获取令牌 api 调用。 使用表单数据通过api调用创建订单。 通过 api 调用获取支付提供商令牌。 进入付款页面。

在前端使用 React-redux-saga。

请在下面的代码:

function* addToCartCamp(action) 
  try 

    // User creation and login
    yield put( type: authActions.AUTH_REGISTER_REQUEST, ...createUser );
    yield put( type: authActions.AUTH_REGISTER_SUCCESS, ...userdata );
    yield put( type: authActions.AUTH_LOGIN_REQUEST, ...login );

    //Create order
    const  data  = yield orderAPI.addToCartCamp(action);
    yield put( type: orderActions.ADD_TO_CART_SUCCESS, ...data );
    yield put( type: orderActions.GET_DETAIL_ORDER_REQUEST, ...orderId: order_id );

    //Handle Payment
     if(action.payment.method === 'creditCard')
      yield put( type: orderActions.TOKEN_REQUEST, ...orderId: order_id );
      else
      yield put( type: orderActions.BANK_TRANSFER_REQUEST, ...orderId: order_id );
     
   catch (error) 
      // handle error message
  

我可以在 saga 文件中调用多个 Yield put,然后调用 api。调用此函数时,后端甚至在用户创建和登录之前就开始订单创建过程。

我需要所有进程同步运行,但它们当前以异步方式运行。

新的传奇和反应。怎么办?

【问题讨论】:

【参考方案1】:

tl;dr:您需要take() 一个动作和call() api 以在put() 成功动作之前产生其结果。

示例

function* addToCartCamp(action) 
  try 
    const action = yield take(authActions.AUTH_REGISTER_REQUEST);
    const userToCreate = action.payload;

    const userData = yield call(authApi.createUser, userToCreate);
    yield put( type: authActions.AUTH_REGISTER_SUCCESS, userData );

    const sessionData = yield call(authApi.loginUser, userData);
    yield put( type: authActions.AUTH_LOGIN_SUCCESS, sessionData );

    // ...
  

补充说明

在我看来,你在一个传奇中发生了太多事情。为什么要在创建订单的同一个地方注册用户?我会将这两个用例分成两个不同的 saga,因为您可能有一个已经注册的用户,只需要在购买之前登录。不要在您的订单传奇中处理身份验证,让 API 处理身份验证失败。

说到这里,你还应该有 api 调用失败的动作。因此,当服务器返回 401 时,因为用户无权购物,您应该 yield put 使用特定的 orderActions.SOMETHING_FAILURE 操作,其中包含存储错误消息、处理挂起状态等的减速器。

拥有全局 try catch 块会使调试变得非常困难,应该避免。见https://github.com/redux-saga/redux-saga/blob/master/docs/basics/ErrorHandling.md(最后一个代码示例):

import Api from './path/to/api'
import  call, put  from 'redux-saga/effects'

function fetchProductsApi() 
  return Api.fetch('/products')
    .then(response => ( response ))
    .catch(error => ( error ))


function* fetchProducts() 
  const  response, error  = yield call(fetchProductsApi)
  if (response) 
    yield put( type: 'PRODUCTS_RECEIVED', products: response )
   else 
    yield put( type: 'PRODUCTS_REQUEST_FAILED', error )
  

【讨论】:

感谢您的建议。我将帐户创建和登录移动到页面中的不同按钮操作,然后休息到不同的按钮操作。现在可以顺利运行,没有任何问题。 很高兴我能帮上忙。顺便说一句,如果我的回答解决了您的问题,您可以接受并投票赞成。

以上是关于在 react redux saga 中处理同步的主要内容,如果未能解决你的问题,请参考以下文章

如何使用React钩子处理/链接依赖于另一个的同步副作用

如何使用 React 钩子处理/链接依赖于另一个的同步副作用

redux-saga的简单使用——saga的模块化拆分——saga进行网络请求——同步修改状态

redux-saga的简单使用——saga的模块化拆分——saga进行网络请求——同步修改状态

第一次下载 React 包时 Redux SAGA sideEffect 处理程序不起作用

从 redux-saga 函数访问 React 上下文值