异步确实等待数据在 redux-thunk 函数中返回
Async does wait for data to be returned in a redux-thunk function
我一直在尝试用来自我的 mongo-db 领域数据库的数据填充我的 redux 存储。
每当我 运行 下面的函数都会执行得很好,但问题是数据会延迟,最终不会到达我的 redux 存储。
我的 thunk 函数:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
try {
return await Realm.open(config).then(async (projectRealm) => {
let syncItems = await projectRealm.objects("Item");
await syncItems.addListener((x, changes) => {
x.map(async (b) => {
console.log(b);
return b;
});
});
});
} catch (error) {
console.log(error);
throw error;
}
}
);
和我的 redux 减速器:
extraReducers: (builder) => {
builder.addCase(addItemsTest.fulfilled, (state, { payload }: any) => {
try {
console.log("from add Items");
console.log(payload);
state.push(payload);
} catch (error) {
console.log(error)
}
});
}
预期结果:
我的 redux 商店应该有这些数据一次 addItemsTest
return something:
[{
itemCode: 1,
itemDescription: 'Soccer Ball',
itemPrice: '35',
partition: 'partitionValue',
},
{
itemCode: 2,
itemDescription: 'Base Ball',
itemPrice: '60',
partition: 'partitionValue',
}
]
实际结果:
混合语法
您正在以一种非常混乱的方式组合 await
/async
和 Promise.then()
语法。混合使用这两种语法不是错误,但我不推荐这样做。坚持 await
/async
无效Return
您的操作实际上 return 现在没有任何价值,因为您的内部 then
函数没有 return 任何东西。唯一的 return
位于 then
内部,位于 x.map
回调中。 await syncItems
是映射器 的 returned 值 ,不适用于您的函数。
现在,这是你的 thunk 所做的:
- 打开一个连接
- 从领域获取物品
- 为那些记录更改的项目添加侦听器
- returns 一个
Promise
解析为 void
解决方案
我相信你想要的是这个:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
try {
const projectRealm = await Realm.open(config);
const syncItems = await projectRealm.objects("Item");
console.log(syncItems);
return syncItems;
} catch (error) {
console.log(error);
throw error;
}
}
);
没有日志记录,可以简化为:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
const projectRealm = await Realm.open(config);
return await projectRealm.objects("Item");
}
);
您不需要 catch
错误,因为 createAsyncThunk
将通过调度错误操作来处理错误。
编辑:监听更改
您的意图似乎是将您的 redux 存储与您的 Realm collection 中的更改同步。因此,您想向调用 dispatch
的 collection 添加一个侦听器,并执行一些操作来处理更改。
这里我假设此操作采用一个数组,其中包含您 collection 中的所有项目。像这样:
const processItems = createAction("processItems", (items: Item[]) => ({
payload: items
}));
替换您所在州的整个数组是最简单的方法。当你用相同的版本替换项目 object 时,它会导致一些不必要的 re-renders,但这不是什么大问题。
或者,您可以传递 changes 的特定属性,例如 insertions
并在 case-by-case 基础上在您的减速器中处理它们。
为了添加调度 processItems
的侦听器,我们需要访问两个变量:领域 config
和 redux dispatch
。您可以在您的组件中或通过调用“init”操作来执行此操作。我不认为真的有太大区别。如果你愿意,你可以在你的减速器中做一些事情来响应“init”动作。
这是一个添加监听器的函数。 Realm.Results
object 是“array-like”,但不完全是一个数组,因此我们使用 [...x]
将其转换为数组。
仅供参考,此函数可能会引发错误。如果在 createAsyncThunk
中使用这很好,但在组件中我们希望 catch
那些错误。
const loadCollection = async (config: Realm.Configuration, dispatch: Dispatch): Promise<void> => {
const projectRealm = await Realm.open(config);
const collection = await projectRealm.objects<Item>("Item");
collection.addListener((x, changes) => {
dispatch(processItems([...x]));
});
}
通过中间 addListener
动作创建者添加侦听器:
export const addListener = createAsyncThunk(
"init",
async (config: Realm.Configuration, { dispatch }) => {
return await loadCollection(config, dispatch);
}
);
// is config a prop or an imported global variable?
const InitComponent = ({config}: {config: Realm.Configuration}) => {
const dispatch = useDispatch();
useEffect( () => {
dispatch(addListener(config));
}, [config, dispatch]);
/* ... */
}
直接添加监听器:
const EffectComponent = ({config}: {config: Realm.Configuration}) => {
const dispatch = useDispatch();
useEffect( () => {
// async action in a useEffect need to be defined and then called
const addListener = async () => {
try {
loadCollection(config, dispatch);
} catch (e) {
console.error(e);
}
}
addListener();
}, [config, dispatch]);
/* ... */
}
我一直在尝试用来自我的 mongo-db 领域数据库的数据填充我的 redux 存储。 每当我 运行 下面的函数都会执行得很好,但问题是数据会延迟,最终不会到达我的 redux 存储。
我的 thunk 函数:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
try {
return await Realm.open(config).then(async (projectRealm) => {
let syncItems = await projectRealm.objects("Item");
await syncItems.addListener((x, changes) => {
x.map(async (b) => {
console.log(b);
return b;
});
});
});
} catch (error) {
console.log(error);
throw error;
}
}
);
和我的 redux 减速器:
extraReducers: (builder) => {
builder.addCase(addItemsTest.fulfilled, (state, { payload }: any) => {
try {
console.log("from add Items");
console.log(payload);
state.push(payload);
} catch (error) {
console.log(error)
}
});
}
预期结果:
我的 redux 商店应该有这些数据一次 addItemsTest
return something:
[{
itemCode: 1,
itemDescription: 'Soccer Ball',
itemPrice: '35',
partition: 'partitionValue',
},
{
itemCode: 2,
itemDescription: 'Base Ball',
itemPrice: '60',
partition: 'partitionValue',
}
]
实际结果:
混合语法
您正在以一种非常混乱的方式组合 await
/async
和 Promise.then()
语法。混合使用这两种语法不是错误,但我不推荐这样做。坚持 await
/async
无效Return
您的操作实际上 return 现在没有任何价值,因为您的内部 then
函数没有 return 任何东西。唯一的 return
位于 then
内部,位于 x.map
回调中。 await syncItems
是映射器 的 returned 值 ,不适用于您的函数。
现在,这是你的 thunk 所做的:
- 打开一个连接
- 从领域获取物品
- 为那些记录更改的项目添加侦听器
- returns 一个
Promise
解析为void
解决方案
我相信你想要的是这个:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
try {
const projectRealm = await Realm.open(config);
const syncItems = await projectRealm.objects("Item");
console.log(syncItems);
return syncItems;
} catch (error) {
console.log(error);
throw error;
}
}
);
没有日志记录,可以简化为:
export const addItemsTest = createAsyncThunk(
"addItems",
async (config: any) => {
const projectRealm = await Realm.open(config);
return await projectRealm.objects("Item");
}
);
您不需要 catch
错误,因为 createAsyncThunk
将通过调度错误操作来处理错误。
编辑:监听更改
您的意图似乎是将您的 redux 存储与您的 Realm collection 中的更改同步。因此,您想向调用 dispatch
的 collection 添加一个侦听器,并执行一些操作来处理更改。
这里我假设此操作采用一个数组,其中包含您 collection 中的所有项目。像这样:
const processItems = createAction("processItems", (items: Item[]) => ({
payload: items
}));
替换您所在州的整个数组是最简单的方法。当你用相同的版本替换项目 object 时,它会导致一些不必要的 re-renders,但这不是什么大问题。
或者,您可以传递 changes 的特定属性,例如 insertions
并在 case-by-case 基础上在您的减速器中处理它们。
为了添加调度 processItems
的侦听器,我们需要访问两个变量:领域 config
和 redux dispatch
。您可以在您的组件中或通过调用“init”操作来执行此操作。我不认为真的有太大区别。如果你愿意,你可以在你的减速器中做一些事情来响应“init”动作。
这是一个添加监听器的函数。 Realm.Results
object 是“array-like”,但不完全是一个数组,因此我们使用 [...x]
将其转换为数组。
仅供参考,此函数可能会引发错误。如果在 createAsyncThunk
中使用这很好,但在组件中我们希望 catch
那些错误。
const loadCollection = async (config: Realm.Configuration, dispatch: Dispatch): Promise<void> => {
const projectRealm = await Realm.open(config);
const collection = await projectRealm.objects<Item>("Item");
collection.addListener((x, changes) => {
dispatch(processItems([...x]));
});
}
通过中间 addListener
动作创建者添加侦听器:
export const addListener = createAsyncThunk(
"init",
async (config: Realm.Configuration, { dispatch }) => {
return await loadCollection(config, dispatch);
}
);
// is config a prop or an imported global variable?
const InitComponent = ({config}: {config: Realm.Configuration}) => {
const dispatch = useDispatch();
useEffect( () => {
dispatch(addListener(config));
}, [config, dispatch]);
/* ... */
}
直接添加监听器:
const EffectComponent = ({config}: {config: Realm.Configuration}) => {
const dispatch = useDispatch();
useEffect( () => {
// async action in a useEffect need to be defined and then called
const addListener = async () => {
try {
loadCollection(config, dispatch);
} catch (e) {
console.error(e);
}
}
addListener();
}, [config, dispatch]);
/* ... */
}