2016-12-07 51 views
0

我来自Redux Thunk,所以我是Redux Saga的全新品牌。我设法实现了一些简单的接通呼叫,但我正在努力应对更复杂的解决方案,并想知道您是否能够指引我朝着正确的方向前进。Redux Saga - 复杂控制流程

我正在创建一个仓库应用程序,该应用程序使用Redux Persist将离职的订单存储,然后在我有连接时定期将其同步回服务器。为了同步他们我有两个API调用,我需要独立做出,并依次是:

  1. 更新采摘量
  2. 确认挑

我重视我下面的终极版状态的样本。如果您查看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; 
    } 

回答

0

如何:

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); 
    } 
} 

请注意,我也是一个很新的redux-saga。我建议你看看https://redux-saga.github.io/redux-saga/docs/advanced/TaskCancellation.html