我来自Redux Thunk所以我是Redux Saga的新手。我设法实现了一些简单的takeEvery调用,但我正在努力解决一个更复杂的解决方案,并想知道你是否能指出我正确的方向。
我正在创建一个仓库应用程序,它使用Redux Persist离线存储已挑选的订单,然后在我建立连接时定期将它们同步回服务器。为了同步它们,我有两个api调用,我需要按顺序独立完成:
我在下面附上了我的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;
}
答案 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