Redux Saga - 复杂的控制流程

时间:2016-12-07 11:59:19

标签: react-native redux react-redux redux-saga

我来自Redux Thunk所以我是Redux Saga的新手。我设法实现了一些简单的takeEvery调用,但我正在努力解决一个更复杂的解决方案,并想知道你是否能指出我正确的方向。

我正在创建一个仓库应用程序,它使用Redux Persist离线存储已挑选的订单,然后在我建立连接时定期将它们同步回服务器。为了同步它们,我有两个api调用,我需要按顺序独立完成:

  1. 更新拣配数量
  2. 确认选择
  3. 我在下面附上了我的Redux状态示例。如果查看ordersToSync,我必须首先使用第一种方法(单独)回发PickedQuantity和PickingListDetailId,然后使用第二种方法使用PickListId确认选择。

    到目前为止,我已设法创建一个es6生成器来模拟我想要的行为,使用一些标志来检查连接,数据是同步还是有错误。如果您将我附加的代码复制并粘贴到https://stephengrider.github.io/JSPlaygrounds/并检查控制台,请查看所需的结果。

    我正在努力将此应用于Redux Saga,因此这个过程可以作为非阻塞调用在后台运行。任何人都可以帮助我指出正确的方向吗?

    非常感谢提前。

        // Example Sync Queue (Persisted Redux state)
        const ordersToSync = [
            {
            "pickingListId": 2362,
            "itemsPicked": [
              {
                "PickingListDetailId": 3115,
                "ProductId": 3387,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 2,
                "PickedQuantity": 2
              },
              {
                "PickingListDetailId": 3114,
                "ProductId": 3386,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 3,
                "PickedQuantity": 1
              },
              {
                "PickingListDetailId": 3116,
                "ProductId": 3385,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 4,
                "PickedQuantity": 4
              }
            ]
          },
          {
            "pickingListId": 2374,
            "itemsPicked": [
              {
                "PickingListDetailId": 3105,
                "ProductId": 3088,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 1,
                "PickedQuantity": 1
              }
            ]
          },
          {
            "pickingListId": 2322,
            "itemsPicked": [
              {
                "PickingListDetailId": 3101,
                "ProductId": 3187,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 2,
                "PickedQuantity": 2
              },
              {
                "PickingListDetailId": 3118,
                "ProductId": 3286,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 3,
                "PickedQuantity": 1
              },
              {
                "PickingListDetailId": 3125,
                "ProductId": 3325,
                "ProductSKU": "123XP",
                "ProductTitle": "Frameset",
                "PickQuantity": 4,
                "PickedQuantity": 4
              }
            ]
          },
        ];
    
        // Represents Redux Reducer
        const error = false; // Flip if error comes back from axios request
        const syncing = false; // Flip whilst axios request does its thing
        const connectionType = 'WIFI'; // Toggled by
    
        // ES6 generator for dispatching sync actions
        function* OrderIterator() {
          // If we have a suitable connection (NetInfo connection type)
          if (connectionType === 'WIFI') {
            // If we are not already syncing some data
            // And we have no errors
            if (!syncing && !error) {
              for (const order of ordersToSync) {
                for (const item of order.itemsPicked) {
                  // Dispatch updatePickQuantityAction
                  // 1. Flip the syncing state to true UPDATE_PICK_QUANTITY_START
                  // 2. If there is an error stop everything and flip the error state to true UPDATE_PICK_QUANTITY_FAIL
                  // 3. If everything goes well with the request, flip the syncing state to false and carry on UPDATE_PICK_QUANTITY_SUCCESS
                  yield console.log(`this.props.updatePickQuantityAction(${item.PickedQuantity}, ${item.PickingListDetailId});`);
                }
                if(!syncing && !error) {
                  // Dispatch confirmPickAction
                  // 1. Flip the syncing state to true CONFIRM_PICK_START
                  // 2. If there is an error stop everything and flip the error state to true CONFIRM_PICK_FAIL
                  // 3. If everything goes well with the request, flip the syncing state to false and carry on CONFIRM_PICK_SUCCESS
                    yield console.log(`this.props.confirmPickAction(${order.pickingListId});`);
                }
                // Dispatch removeConfirmedPickAction
                // This will remove the pick from sync queue (Redux state not API) after it has been confirmed
                console.log(`this.props.removeConfirmedPickAction();`);
              }
            }
          }
        }
    
        const SyncOrders = OrderIterator();
    
        for (const item of SyncOrders) {
            item;
        }
    

1 个答案:

答案 0 :(得分:1)

这个怎么样:

Ho

请注意,我对export const ordersToSync = state => state.ordersToSync; export const getLastSavedItemId = state => state.lastSavedItemId; export const getItemFailedOnConfirm = state => state.itemFailedOnCofirm; export function *syncDataIdea() { const ordersToSync = yield select(ordersToSync); for (const order of ordersToSync) { for (const item of order.itemsPicked) { yield call(updatePickQuantityAction, item.PickedQuantity); } yield call(confirmPickAction, order.pickingListId); yield call(removeConfirmedPickAction, order.pickingListId); } } export function *syncData() { const ordersToSync = yield select(ordersToSync); for (const order of ordersToSync) { const itemFailedOnConfirm = yield select(getItemFailedOnConfirm); if (itemFailedOnConfirm === null) { const lastSavedItemId = yield select(getLastSavedItemId); for (const item of order.itemsPicked) { const itemId = item.PickedQuantity.PickingListDetailId; try { if (lastSavedItemId !== null && lastSavedItemId !== itemId) { continue; } yield call(updatePickQuantityAction, item.PickedQuantity); yield put({type: 'SET_LAST_SAVED_ITEM', getLastSavedItemId: null}); } catch (error) { yield put({ type: 'SET_LAST_SAVED_ITEM', getLastSavedItemId: itemId }); } finally { if (yield cancelled()) { yield put({ type: 'SET_LAST_SAVED_ITEM', getLastSavedItemId: itemId }); } } } } try { yield call(confirmPickAction, order.pickingListId); yield put({type: 'ITEM_FAILED_ON_CONFIRM', pickingListId: null}); } catch (error) { yield put({type: 'ITEM_FAILED_ON_CONFIRM', pickingListId: order.pickingListId}); } finally { if (yield cancelled()) { yield put({type: 'ITEM_FAILED_ON_CONFIRM', pickingListId: order.pickingListId}); } } yield call(removeConfirmedPickAction, order.pickingListId); } } function* main() { while (yield take('WIFI_ON')) { const syncDataTask = yield fork(syncData); yield take('WIFI_OFF'); yield cancel(syncDataTask); } } 也很陌生。我建议你看看https://redux-saga.github.io/redux-saga/docs/advanced/TaskCancellation.html